pyqrack-cuda 1.56.0__tar.gz → 1.57.1__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_cuda-1.56.0/pyqrack_cuda.egg-info → pyqrack_cuda-1.57.1}/PKG-INFO +1 -1
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/qrack_ace_backend.py +317 -261
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1/pyqrack_cuda.egg-info}/PKG-INFO +1 -1
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/setup.py +1 -1
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/LICENSE +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/MANIFEST.in +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/Makefile +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/README.md +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyproject.toml +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/__init__.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/pauli.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack_cuda.egg-info/SOURCES.txt +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack_cuda.egg-info/dependency_links.txt +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack_cuda.egg-info/not-zip-safe +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack_cuda.egg-info/requires.txt +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/pyqrack_cuda.egg-info/top_level.txt +0 -0
- {pyqrack_cuda-1.56.0 → pyqrack_cuda-1.57.1}/setup.cfg +0 -0
@@ -168,7 +168,8 @@ class QrackAceBackend:
|
|
168
168
|
def __init__(
|
169
169
|
self,
|
170
170
|
qubit_count=1,
|
171
|
-
long_range_columns=
|
171
|
+
long_range_columns=5,
|
172
|
+
long_range_rows=2,
|
172
173
|
is_transpose=False,
|
173
174
|
isTensorNetwork=False,
|
174
175
|
isSchmidtDecomposeMulti=False,
|
@@ -187,6 +188,7 @@ class QrackAceBackend:
|
|
187
188
|
if toClone:
|
188
189
|
qubit_count = toClone.num_qubits()
|
189
190
|
long_range_columns = toClone.long_range_columns
|
191
|
+
long_range_rows = toClone.long_range_rows
|
190
192
|
is_transpose = toClone.is_transpose
|
191
193
|
if qubit_count < 0:
|
192
194
|
qubit_count = 0
|
@@ -195,6 +197,7 @@ class QrackAceBackend:
|
|
195
197
|
|
196
198
|
self._factor_width(qubit_count, is_transpose)
|
197
199
|
self.long_range_columns = long_range_columns
|
200
|
+
self.long_range_rows = long_range_rows
|
198
201
|
self.is_transpose = is_transpose
|
199
202
|
|
200
203
|
fppow = 5
|
@@ -209,45 +212,68 @@ class QrackAceBackend:
|
|
209
212
|
|
210
213
|
self._coupling_map = None
|
211
214
|
|
212
|
-
# If there's only one or zero "False" columns,
|
215
|
+
# If there's only one or zero "False" columns or rows,
|
213
216
|
# the entire simulator is connected, anyway.
|
214
217
|
len_col_seq = long_range_columns + 1
|
215
|
-
|
216
|
-
if (long_range_columns + 1) >= self._row_length:
|
218
|
+
col_patch_count = (self._row_length + len_col_seq - 1) // len_col_seq
|
219
|
+
if (self._row_length < 3) or ((long_range_columns + 1) >= self._row_length):
|
217
220
|
self._is_col_long_range = [True] * self._row_length
|
218
221
|
else:
|
219
222
|
col_seq = [True] * long_range_columns + [False]
|
220
|
-
self._is_col_long_range = (col_seq *
|
223
|
+
self._is_col_long_range = (col_seq * col_patch_count)[: self._row_length]
|
221
224
|
if long_range_columns < self._row_length:
|
222
225
|
self._is_col_long_range[-1] = False
|
226
|
+
len_row_seq = long_range_rows + 1
|
227
|
+
row_patch_count = (self._col_length + len_row_seq - 1) // len_row_seq
|
228
|
+
if (self._col_length < 3) or ((long_range_rows + 1) >= self._col_length):
|
229
|
+
self._is_row_long_range = [True] * self._col_length
|
230
|
+
else:
|
231
|
+
row_seq = [True] * long_range_rows + [False]
|
232
|
+
self._is_row_long_range = (row_seq * row_patch_count)[: self._col_length]
|
233
|
+
if long_range_rows < self._col_length:
|
234
|
+
self._is_row_long_range[-1] = False
|
235
|
+
sim_count = col_patch_count * row_patch_count
|
236
|
+
self._row_offset = 0
|
237
|
+
for r in range(self._col_length):
|
238
|
+
for c in self._is_col_long_range:
|
239
|
+
self._row_offset += 1 if c else 3
|
223
240
|
|
224
241
|
self._qubit_dict = {}
|
225
|
-
self._lhv_dict = {}
|
226
|
-
self._hardware_offset = []
|
227
242
|
sim_counts = [0] * sim_count
|
228
243
|
sim_id = 0
|
229
244
|
tot_qubits = 0
|
230
|
-
for r in
|
245
|
+
for r in self._is_row_long_range:
|
231
246
|
for c in self._is_col_long_range:
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
247
|
+
qubit = [(sim_id, sim_counts[sim_id])]
|
248
|
+
sim_counts[sim_id] += 1
|
249
|
+
|
250
|
+
if (not c) or (not r):
|
251
|
+
t_sim_id = (sim_id + 1) % sim_count
|
252
|
+
qubit.append((t_sim_id, sim_counts[t_sim_id]))
|
253
|
+
sim_counts[t_sim_id] += 1
|
254
|
+
|
255
|
+
qubit.append(
|
256
|
+
LHVQubit(
|
257
|
+
toClone=(
|
258
|
+
toClone._qubit_dict[tot_qubits][2] if toClone else None
|
259
|
+
)
|
260
|
+
)
|
244
261
|
)
|
245
|
-
tot_qubits += 1
|
246
262
|
|
263
|
+
if (not c) and (not r):
|
264
|
+
t_sim_id = (sim_id + col_patch_count) % sim_count
|
265
|
+
qubit.append((t_sim_id, sim_counts[t_sim_id]))
|
266
|
+
sim_counts[t_sim_id] += 1
|
267
|
+
|
268
|
+
t_sim_id = (t_sim_id + 1) % sim_count
|
269
|
+
qubit.append((t_sim_id, sim_counts[t_sim_id]))
|
270
|
+
sim_counts[t_sim_id] += 1
|
271
|
+
|
272
|
+
if not c:
|
247
273
|
sim_id = (sim_id + 1) % sim_count
|
248
|
-
|
249
|
-
|
250
|
-
|
274
|
+
|
275
|
+
self._qubit_dict[tot_qubits] = qubit
|
276
|
+
tot_qubits += 1
|
251
277
|
|
252
278
|
self.sim = []
|
253
279
|
for i in range(sim_count):
|
@@ -362,57 +388,97 @@ class QrackAceBackend:
|
|
362
388
|
self._qec_x(c)
|
363
389
|
|
364
390
|
def _unpack(self, lq):
|
365
|
-
|
391
|
+
return self._qubit_dict[lq]
|
366
392
|
|
367
|
-
|
368
|
-
|
393
|
+
def _get_qb_lhv_indices(self, hq):
|
394
|
+
qb = []
|
395
|
+
if len(hq) < 2:
|
396
|
+
qb = [0]
|
397
|
+
lhv = -1
|
398
|
+
elif len(hq) < 4:
|
399
|
+
qb = [0, 1]
|
400
|
+
lhv = 2
|
401
|
+
else:
|
402
|
+
qb = [0, 1, 3, 4]
|
403
|
+
lhv = 2
|
369
404
|
|
370
|
-
return
|
371
|
-
self._qubit_dict[offset],
|
372
|
-
self._lhv_dict[offset + 1],
|
373
|
-
self._qubit_dict[offset + 2],
|
374
|
-
]
|
405
|
+
return qb, lhv
|
375
406
|
|
376
407
|
def _correct(self, lq, phase=False):
|
377
|
-
|
408
|
+
hq = self._unpack(lq)
|
409
|
+
|
410
|
+
if len(hq) == 1:
|
378
411
|
return
|
379
412
|
|
380
|
-
|
413
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
381
414
|
|
382
415
|
if phase:
|
383
|
-
|
384
|
-
|
385
|
-
|
416
|
+
for q in qb:
|
417
|
+
b = hq[q]
|
418
|
+
self.sim[b[0]].h(b[1])
|
419
|
+
b = hq[lhv]
|
386
420
|
b.h()
|
387
|
-
b = hq[2]
|
388
|
-
self.sim[b[0]].h(b[1])
|
389
421
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
422
|
+
if len(hq) == 5:
|
423
|
+
# RMS
|
424
|
+
p = [
|
425
|
+
self.sim[hq[0][0]].prob(hq[0][1]),
|
426
|
+
self.sim[hq[1][0]].prob(hq[1][1]),
|
427
|
+
hq[2].prob(),
|
428
|
+
self.sim[hq[3][0]].prob(hq[3][1]),
|
429
|
+
self.sim[hq[4][0]].prob(hq[4][1]),
|
430
|
+
]
|
431
|
+
# Balancing suggestion from Elara (the custom OpenAI GPT)
|
432
|
+
prms = math.sqrt(
|
433
|
+
(p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7
|
434
|
+
)
|
435
|
+
qrms = math.sqrt(
|
436
|
+
(
|
437
|
+
(1 - p[0]) ** 2
|
438
|
+
+ (1 - p[1]) ** 2
|
439
|
+
+ 3 * ((1 - p[2]) ** 2)
|
440
|
+
+ (1 - p[3]) ** 2
|
441
|
+
+ (1 - p[4]) ** 2
|
442
|
+
)
|
443
|
+
/ 7
|
444
|
+
)
|
445
|
+
result = ((prms + (1 - qrms)) / 2) >= 0.5
|
446
|
+
syndrome = (
|
447
|
+
[1 - p[0], 1 - p[1], 1 - p[2], 1 - p[3], 1 - p[4]]
|
448
|
+
if result
|
449
|
+
else [p[0], p[1], p[2], p[3], p[4]]
|
450
|
+
)
|
451
|
+
for q in range(5):
|
452
|
+
if syndrome[q] > (0.5 + self._epsilon):
|
453
|
+
if q == 2:
|
454
|
+
hq[q].x()
|
455
|
+
else:
|
456
|
+
self.sim[hq[q][0]].x(hq[q][1])
|
457
|
+
else:
|
458
|
+
# RMS
|
459
|
+
p = [
|
460
|
+
self.sim[hq[0][0]].prob(hq[0][1]),
|
461
|
+
self.sim[hq[1][0]].prob(hq[1][1]),
|
462
|
+
hq[2].prob(),
|
463
|
+
]
|
464
|
+
# Balancing suggestion from Elara (the custom OpenAI GPT)
|
465
|
+
prms = math.sqrt((p[0] ** 2 + p[1] ** 2 + p[2] ** 2) / 3)
|
466
|
+
qrms = math.sqrt(((1 - p[0]) ** 2 + (1 - p[1]) ** 2 + (1 - p[2]) ** 2) / 3)
|
467
|
+
result = ((prms + (1 - qrms)) / 2) >= 0.5
|
468
|
+
syndrome = [1 - p[0], 1 - p[1], 1 - p[2]] if result else [p[0], p[1], p[2]]
|
469
|
+
for q in range(3):
|
470
|
+
if syndrome[q] > (0.5 + self._epsilon):
|
471
|
+
if q == 2:
|
472
|
+
hq[q].x()
|
473
|
+
else:
|
474
|
+
self.sim[hq[q][0]].x(hq[q][1])
|
408
475
|
|
409
476
|
if phase:
|
410
|
-
|
411
|
-
|
412
|
-
|
477
|
+
for q in qb:
|
478
|
+
b = hq[q]
|
479
|
+
self.sim[b[0]].h(b[1])
|
480
|
+
b = hq[lhv]
|
413
481
|
b.h()
|
414
|
-
b = hq[2]
|
415
|
-
self.sim[b[0]].h(b[1])
|
416
482
|
|
417
483
|
def u(self, lq, th, ph, lm):
|
418
484
|
hq = self._unpack(lq)
|
@@ -421,12 +487,14 @@ class QrackAceBackend:
|
|
421
487
|
self.sim[b[0]].u(b[1], th, ph, lm)
|
422
488
|
return
|
423
489
|
|
424
|
-
|
425
|
-
|
426
|
-
|
490
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
491
|
+
|
492
|
+
for q in qb:
|
493
|
+
b = hq[q]
|
494
|
+
self.sim[b[0]].u(b[1], th, ph, lm)
|
495
|
+
|
496
|
+
b = hq[lhv]
|
427
497
|
b.u(th, ph, lm)
|
428
|
-
b = hq[2]
|
429
|
-
self.sim[b[0]].u(b[1], th, ph, lm)
|
430
498
|
|
431
499
|
self._correct(lq, False)
|
432
500
|
self._correct(lq, True)
|
@@ -438,17 +506,19 @@ class QrackAceBackend:
|
|
438
506
|
self.sim[b[0]].r(p, th, b[1])
|
439
507
|
return
|
440
508
|
|
441
|
-
|
442
|
-
|
443
|
-
|
509
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
510
|
+
|
511
|
+
for q in qb:
|
512
|
+
b = hq[q]
|
513
|
+
self.sim[b[0]].r(p, th, b[1])
|
514
|
+
|
515
|
+
b = hq[lhv]
|
444
516
|
if p == Pauli.PauliX:
|
445
517
|
b.rx(th)
|
446
518
|
elif p == Pauli.PauliY:
|
447
519
|
b.ry(th)
|
448
520
|
elif p == Pauli.PauliZ:
|
449
521
|
b.rz(th)
|
450
|
-
b = hq[2]
|
451
|
-
self.sim[b[0]].r(p, th, b[1])
|
452
522
|
|
453
523
|
if p != Pauli.PauliZ:
|
454
524
|
self._correct(lq, False)
|
@@ -463,12 +533,16 @@ class QrackAceBackend:
|
|
463
533
|
return
|
464
534
|
|
465
535
|
self._correct(lq)
|
466
|
-
|
467
|
-
self.
|
468
|
-
|
536
|
+
|
537
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
538
|
+
|
539
|
+
for q in qb:
|
540
|
+
b = hq[q]
|
541
|
+
self.sim[b[0]].h(b[1])
|
542
|
+
|
543
|
+
b = hq[lhv]
|
469
544
|
b.h()
|
470
|
-
|
471
|
-
self.sim[b[0]].h(b[1])
|
545
|
+
|
472
546
|
self._correct(lq)
|
473
547
|
|
474
548
|
def s(self, lq):
|
@@ -478,12 +552,14 @@ class QrackAceBackend:
|
|
478
552
|
self.sim[b[0]].s(b[1])
|
479
553
|
return
|
480
554
|
|
481
|
-
|
482
|
-
|
483
|
-
|
555
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
556
|
+
|
557
|
+
for q in qb:
|
558
|
+
b = hq[q]
|
559
|
+
self.sim[b[0]].s(b[1])
|
560
|
+
|
561
|
+
b = hq[lhv]
|
484
562
|
b.s()
|
485
|
-
b = hq[2]
|
486
|
-
self.sim[b[0]].s(b[1])
|
487
563
|
|
488
564
|
def adjs(self, lq):
|
489
565
|
hq = self._unpack(lq)
|
@@ -492,12 +568,14 @@ class QrackAceBackend:
|
|
492
568
|
self.sim[b[0]].adjs(b[1])
|
493
569
|
return
|
494
570
|
|
495
|
-
|
496
|
-
|
497
|
-
|
571
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
572
|
+
|
573
|
+
for q in qb:
|
574
|
+
b = hq[q]
|
575
|
+
self.sim[b[0]].adjs(b[1])
|
576
|
+
|
577
|
+
b = hq[lhv]
|
498
578
|
b.adjs()
|
499
|
-
b = hq[2]
|
500
|
-
self.sim[b[0]].adjs(b[1])
|
501
579
|
|
502
580
|
def x(self, lq):
|
503
581
|
hq = self._unpack(lq)
|
@@ -506,12 +584,14 @@ class QrackAceBackend:
|
|
506
584
|
self.sim[b[0]].x(b[1])
|
507
585
|
return
|
508
586
|
|
509
|
-
|
510
|
-
|
511
|
-
|
587
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
588
|
+
|
589
|
+
for q in qb:
|
590
|
+
b = hq[q]
|
591
|
+
self.sim[b[0]].x(b[1])
|
592
|
+
|
593
|
+
b = hq[lhv]
|
512
594
|
b.x()
|
513
|
-
b = hq[2]
|
514
|
-
self.sim[b[0]].x(b[1])
|
515
595
|
|
516
596
|
def y(self, lq):
|
517
597
|
hq = self._unpack(lq)
|
@@ -520,12 +600,14 @@ class QrackAceBackend:
|
|
520
600
|
self.sim[b[0]].y(b[1])
|
521
601
|
return
|
522
602
|
|
523
|
-
|
524
|
-
|
525
|
-
|
603
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
604
|
+
|
605
|
+
for q in qb:
|
606
|
+
b = hq[q]
|
607
|
+
self.sim[b[0]].y(b[1])
|
608
|
+
|
609
|
+
b = hq[lhv]
|
526
610
|
b.y()
|
527
|
-
b = hq[2]
|
528
|
-
self.sim[b[0]].y(b[1])
|
529
611
|
|
530
612
|
def z(self, lq):
|
531
613
|
hq = self._unpack(lq)
|
@@ -534,12 +616,14 @@ class QrackAceBackend:
|
|
534
616
|
self.sim[b[0]].z(b[1])
|
535
617
|
return
|
536
618
|
|
537
|
-
|
538
|
-
|
539
|
-
|
619
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
620
|
+
|
621
|
+
for q in qb:
|
622
|
+
b = hq[q]
|
623
|
+
self.sim[b[0]].z(b[1])
|
624
|
+
|
625
|
+
b = hq[lhv]
|
540
626
|
b.z()
|
541
|
-
b = hq[2]
|
542
|
-
self.sim[b[0]].z(b[1])
|
543
627
|
|
544
628
|
def t(self, lq):
|
545
629
|
hq = self._unpack(lq)
|
@@ -548,12 +632,14 @@ class QrackAceBackend:
|
|
548
632
|
self.sim[b[0]].t(b[1])
|
549
633
|
return
|
550
634
|
|
551
|
-
|
552
|
-
|
553
|
-
|
635
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
636
|
+
|
637
|
+
for q in qb:
|
638
|
+
b = hq[q]
|
639
|
+
self.sim[b[0]].t(b[1])
|
640
|
+
|
641
|
+
b = hq[lhv]
|
554
642
|
b.t()
|
555
|
-
b = hq[2]
|
556
|
-
self.sim[b[0]].t(b[1])
|
557
643
|
|
558
644
|
def adjt(self, lq):
|
559
645
|
hq = self._unpack(lq)
|
@@ -562,12 +648,14 @@ class QrackAceBackend:
|
|
562
648
|
self.sim[b[0]].adjt(b[1])
|
563
649
|
return
|
564
650
|
|
565
|
-
|
566
|
-
|
567
|
-
|
651
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
652
|
+
|
653
|
+
for q in qb:
|
654
|
+
b = hq[q]
|
655
|
+
self.sim[b[0]].adjt(b[1])
|
656
|
+
|
657
|
+
b = hq[lhv]
|
568
658
|
b.adjt()
|
569
|
-
b = hq[2]
|
570
|
-
self.sim[b[0]].adjt(b[1])
|
571
659
|
|
572
660
|
def _get_gate(self, pauli, anti, sim_id):
|
573
661
|
gate = None
|
@@ -588,10 +676,47 @@ class QrackAceBackend:
|
|
588
676
|
|
589
677
|
return gate, shadow
|
590
678
|
|
591
|
-
def
|
592
|
-
|
593
|
-
|
679
|
+
def _get_connected(self, i, is_row):
|
680
|
+
long_range = self._is_row_long_range if is_row else self._is_col_long_range
|
681
|
+
length = self._col_length if is_row else self._row_length
|
682
|
+
|
683
|
+
connected = [i]
|
684
|
+
c = (i - 1) % length
|
685
|
+
while long_range[c] and (len(connected) < length):
|
686
|
+
connected.append(c)
|
687
|
+
c = (c - 1) % length
|
688
|
+
if len(connected) < length:
|
689
|
+
connected.append(c)
|
690
|
+
boundary = len(connected)
|
691
|
+
c = (i + 1) % length
|
692
|
+
while long_range[c] and (len(connected) < length):
|
693
|
+
connected.append(c)
|
694
|
+
c = (c + 1) % length
|
695
|
+
if len(connected) < length:
|
696
|
+
connected.append(c)
|
697
|
+
|
698
|
+
return connected, boundary
|
699
|
+
|
700
|
+
def _apply_coupling(self, pauli, anti, qb1, lhv1, hq1, qb2, lhv2, hq2, lq1_lr):
|
701
|
+
for q1 in qb1:
|
702
|
+
if q1 == lhv1:
|
703
|
+
continue
|
704
|
+
b1 = hq1[q1]
|
705
|
+
gate_fn, shadow_fn = self._get_gate(pauli, anti, b1[0])
|
706
|
+
for q2 in qb2:
|
707
|
+
if q2 == lhv2:
|
708
|
+
continue
|
709
|
+
b2 = hq2[q2]
|
710
|
+
if b1[0] == b2[0]:
|
711
|
+
gate_fn([b1[1]], b2[1])
|
712
|
+
elif (
|
713
|
+
lq1_lr
|
714
|
+
or (b1[1] == b2[1])
|
715
|
+
or ((len(qb1) == 2) and (b1[1] == (b2[1] & 1)))
|
716
|
+
):
|
717
|
+
shadow_fn(b1, b2)
|
594
718
|
|
719
|
+
def _cpauli(self, lq1, lq2, anti, pauli):
|
595
720
|
lq1_row = lq1 // self._row_length
|
596
721
|
lq1_col = lq1 % self._row_length
|
597
722
|
lq2_row = lq2 // self._row_length
|
@@ -600,102 +725,23 @@ class QrackAceBackend:
|
|
600
725
|
hq1 = self._unpack(lq1)
|
601
726
|
hq2 = self._unpack(lq2)
|
602
727
|
|
603
|
-
|
604
|
-
|
605
|
-
(self.long_range_columns + 1) >= self._row_length
|
606
|
-
)
|
607
|
-
c = (lq1_col - 1) % self._row_length
|
608
|
-
while not connected and self._is_col_long_range[c]:
|
609
|
-
connected = lq2_col == c
|
610
|
-
c = (c - 1) % self._row_length
|
611
|
-
c = (lq1_col + 1) % self._row_length
|
612
|
-
while not connected and self._is_col_long_range[c]:
|
613
|
-
connected = lq2_col == c
|
614
|
-
c = (c + 1) % self._row_length
|
615
|
-
|
616
|
-
b1 = hq1[0]
|
617
|
-
b2 = hq2[0]
|
618
|
-
gate, shadow = self._get_gate(pauli, anti, b1[0])
|
619
|
-
if connected:
|
620
|
-
gate([b1[1]], b2[1])
|
621
|
-
else:
|
622
|
-
shadow(b1, b2)
|
623
|
-
return
|
624
|
-
|
625
|
-
if self._row_length == 2:
|
626
|
-
gate, shadow = self._get_gate(pauli, anti, hq1[2][0])
|
627
|
-
gate([hq1[2][1]], hq2[0][1])
|
628
|
-
gate, shadow = self._get_gate(pauli, anti, hq1[0][0])
|
629
|
-
gate([hq1[0][1]], hq2[2][1])
|
630
|
-
_cpauli_lhv(hq1[1].prob(), hq2[1], pauli, anti)
|
631
|
-
return
|
632
|
-
|
633
|
-
connected_cols = []
|
634
|
-
c = (lq1_col - 1) % self._row_length
|
635
|
-
while self._is_col_long_range[c] and (
|
636
|
-
len(connected_cols) < (self._row_length - 1)
|
637
|
-
):
|
638
|
-
connected_cols.append(c)
|
639
|
-
c = (c - 1) % self._row_length
|
640
|
-
if len(connected_cols) < (self._row_length - 1):
|
641
|
-
connected_cols.append(c)
|
642
|
-
boundary = len(connected_cols)
|
643
|
-
c = (lq1_col + 1) % self._row_length
|
644
|
-
while self._is_col_long_range[c] and (
|
645
|
-
len(connected_cols) < (self._row_length - 1)
|
646
|
-
):
|
647
|
-
connected_cols.append(c)
|
648
|
-
c = (c + 1) % self._row_length
|
649
|
-
if len(connected_cols) < (self._row_length - 1):
|
650
|
-
connected_cols.append(c)
|
728
|
+
lq1_lr = len(hq1) == 1
|
729
|
+
lq2_lr = len(hq2) == 1
|
651
730
|
|
652
731
|
self._correct(lq1)
|
653
732
|
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
_cpauli_lhv(hq1[1].prob(), hq2[1], pauli, anti)
|
667
|
-
elif lq2_col in connected_cols:
|
668
|
-
# lq1_col < lq2_col
|
669
|
-
gate, shadow = self._get_gate(pauli, anti, hq2[0][0])
|
670
|
-
if lq1_lr:
|
671
|
-
gate([hq1[0][1]], hq2[0][1])
|
672
|
-
shadow(hq1[0], hq2[2])
|
673
|
-
_cpauli_lhv(self.sim[hq1[0][0]].prob(hq1[0][1]), hq2[1], pauli, anti)
|
674
|
-
elif lq2_lr:
|
675
|
-
gate([hq1[2][1]], hq2[0][1])
|
676
|
-
else:
|
677
|
-
gate([hq1[2][1]], hq2[0][1])
|
678
|
-
shadow(hq1[0], hq2[2])
|
679
|
-
_cpauli_lhv(hq1[1].prob(), hq2[1], pauli, anti)
|
680
|
-
elif lq1_col == lq2_col:
|
681
|
-
# Both are in the same boundary column.
|
682
|
-
b = hq1[0]
|
683
|
-
gate, shadow = self._get_gate(pauli, anti, b[0])
|
684
|
-
gate([b[1]], hq2[0][1])
|
685
|
-
_cpauli_lhv(hq1[1].prob(), hq2[1], pauli, anti)
|
686
|
-
b = hq1[2]
|
687
|
-
gate, shadow = self._get_gate(pauli, anti, b[0])
|
688
|
-
gate([b[1]], hq2[2][1])
|
689
|
-
else:
|
690
|
-
# The qubits have no quantum connection.
|
691
|
-
gate, shadow = self._get_gate(pauli, anti, hq1[0][0])
|
692
|
-
shadow(hq1[0], hq2[0])
|
693
|
-
if lq1_lr:
|
694
|
-
shadow(hq1[0], hq2[2])
|
695
|
-
shadow(hq1[0], hq2[1])
|
696
|
-
elif not lq2_lr:
|
697
|
-
_cpauli_lhv(hq1[1].prob(), hq2[1], pauli, anti)
|
698
|
-
shadow(hq1[2], hq2[2])
|
733
|
+
qb1, lhv1 = self._get_qb_lhv_indices(hq1)
|
734
|
+
qb2, lhv2 = self._get_qb_lhv_indices(hq2)
|
735
|
+
# Apply cross coupling on hardware qubits first
|
736
|
+
self._apply_coupling(pauli, anti, qb1, lhv1, hq1, qb2, lhv2, hq2, lq1_lr)
|
737
|
+
# Apply coupling to the local-hidden-variable target
|
738
|
+
if lhv2 >= 0:
|
739
|
+
_cpauli_lhv(
|
740
|
+
hq1[lhv1].prob() if lhv1 >= 0 else self.sim[hq1[0][0]].prob(hq1[0][1]),
|
741
|
+
hq2[lhv2],
|
742
|
+
pauli,
|
743
|
+
anti,
|
744
|
+
)
|
699
745
|
|
700
746
|
self._correct(lq1, True)
|
701
747
|
if pauli != Pauli.PauliZ:
|
@@ -787,14 +833,39 @@ class QrackAceBackend:
|
|
787
833
|
return self.sim[b[0]].prob(b[1])
|
788
834
|
|
789
835
|
self._correct(lq)
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
836
|
+
if len(hq) == 5:
|
837
|
+
# RMS
|
838
|
+
p = [
|
839
|
+
self.sim[hq[0][0]].prob(hq[0][1]),
|
840
|
+
self.sim[hq[1][0]].prob(hq[1][1]),
|
841
|
+
hq[2].prob(),
|
842
|
+
self.sim[hq[3][0]].prob(hq[3][1]),
|
843
|
+
self.sim[hq[4][0]].prob(hq[4][1]),
|
844
|
+
]
|
845
|
+
# Balancing suggestion from Elara (the custom OpenAI GPT)
|
846
|
+
prms = math.sqrt(
|
847
|
+
(p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7
|
848
|
+
)
|
849
|
+
qrms = math.sqrt(
|
850
|
+
(
|
851
|
+
(1 - p[0]) ** 2
|
852
|
+
+ (1 - p[1]) ** 2
|
853
|
+
+ 3 * ((1 - p[2]) ** 2)
|
854
|
+
+ (1 - p[3]) ** 2
|
855
|
+
+ (1 - p[4]) ** 2
|
856
|
+
)
|
857
|
+
/ 7
|
858
|
+
)
|
859
|
+
else:
|
860
|
+
# RMS
|
861
|
+
p = [
|
862
|
+
self.sim[hq[0][0]].prob(hq[0][1]),
|
863
|
+
self.sim[hq[1][0]].prob(hq[1][1]),
|
864
|
+
hq[2].prob(),
|
865
|
+
]
|
866
|
+
# Balancing suggestion from Elara (the custom OpenAI GPT)
|
867
|
+
prms = math.sqrt((p[0] ** 2 + p[1] ** 2 + p[2] ** 2) / 3)
|
868
|
+
qrms = math.sqrt(((1 - p[0]) ** 2 + (1 - p[1]) ** 2 + (1 - p[2]) ** 2) / 3)
|
798
869
|
|
799
870
|
return (prms + (1 - qrms)) / 2
|
800
871
|
|
@@ -807,44 +878,47 @@ class QrackAceBackend:
|
|
807
878
|
p = self.prob(lq)
|
808
879
|
result = ((p + self._epsilon) >= 1) or (random.random() < p)
|
809
880
|
|
810
|
-
|
811
|
-
p = self.sim[b[0]].prob(b[1]) if result else (1 - self.sim[b[0]].prob(b[1]))
|
812
|
-
if p < self._epsilon:
|
813
|
-
if self.sim[b[0]].m(b[1]) != result:
|
814
|
-
self.sim[b[0]].x(b[1])
|
815
|
-
else:
|
816
|
-
self.sim[b[0]].force_m(b[1], result)
|
881
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
817
882
|
|
818
|
-
|
883
|
+
for q in qb:
|
884
|
+
b = hq[q]
|
885
|
+
p = self.sim[b[0]].prob(b[1]) if result else (1 - self.sim[b[0]].prob(b[1]))
|
886
|
+
if p < self._epsilon:
|
887
|
+
if self.sim[b[0]].m(b[1]) != result:
|
888
|
+
self.sim[b[0]].x(b[1])
|
889
|
+
else:
|
890
|
+
self.sim[b[0]].force_m(b[1], result)
|
891
|
+
|
892
|
+
b = hq[lhv]
|
819
893
|
b.reset()
|
820
894
|
if result:
|
821
895
|
b.x()
|
822
896
|
|
823
|
-
b = hq[2]
|
824
|
-
p = self.sim[b[0]].prob(b[1]) if result else (1 - self.sim[b[0]].prob(b[1]))
|
825
|
-
if p < self._epsilon:
|
826
|
-
if self.sim[b[0]].m(b[1]) != result:
|
827
|
-
self.sim[b[0]].x(b[1])
|
828
|
-
else:
|
829
|
-
self.sim[b[0]].force_m(b[1], result)
|
830
|
-
|
831
897
|
return result
|
832
898
|
|
833
|
-
def force_m(self, lq,
|
899
|
+
def force_m(self, lq, result):
|
834
900
|
hq = self._unpack(lq)
|
835
901
|
if len(hq) < 2:
|
836
902
|
b = hq[0]
|
837
|
-
return self.sim[b[0]].force_m(b[1])
|
903
|
+
return self.sim[b[0]].force_m(b[1], result)
|
838
904
|
|
839
905
|
self._correct(lq)
|
906
|
+
|
907
|
+
qb, lhv = self._get_qb_lhv_indices(hq)
|
908
|
+
|
909
|
+
for q in qb:
|
910
|
+
b = hq[q]
|
911
|
+
p = self.sim[b[0]].prob(b[1]) if result else (1 - self.sim[b[0]].prob(b[1]))
|
912
|
+
if p < self._epsilon:
|
913
|
+
if self.sim[b[0]].m(b[1]) != result:
|
914
|
+
self.sim[b[0]].x(b[1])
|
915
|
+
else:
|
916
|
+
self.sim[b[0]].force_m(b[1], result)
|
917
|
+
|
840
918
|
b = hq[1]
|
841
919
|
b.reset()
|
842
|
-
if
|
920
|
+
if result:
|
843
921
|
b.x()
|
844
|
-
b = hq[0]
|
845
|
-
self.sim[b[0]].force_m(b[1], c)
|
846
|
-
b = hq[2]
|
847
|
-
self.sim[b[0]].force_m(b[1], c)
|
848
922
|
|
849
923
|
return c
|
850
924
|
|
@@ -1227,28 +1301,12 @@ class QrackAceBackend:
|
|
1227
1301
|
return row * cols + col
|
1228
1302
|
|
1229
1303
|
for col in range(cols):
|
1230
|
-
connected_cols =
|
1231
|
-
c = (col - 1) % cols
|
1232
|
-
while self._is_col_long_range[c] and (
|
1233
|
-
len(connected_cols) < self._row_length
|
1234
|
-
):
|
1235
|
-
connected_cols.append(c)
|
1236
|
-
c = (c - 1) % cols
|
1237
|
-
if len(connected_cols) < self._row_length:
|
1238
|
-
connected_cols.append(c)
|
1239
|
-
c = (col + 1) % cols
|
1240
|
-
while self._is_col_long_range[c] and (
|
1241
|
-
len(connected_cols) < self._row_length
|
1242
|
-
):
|
1243
|
-
connected_cols.append(c)
|
1244
|
-
c = (c + 1) % cols
|
1245
|
-
if len(connected_cols) < self._row_length:
|
1246
|
-
connected_cols.append(c)
|
1247
|
-
|
1304
|
+
connected_cols, _ = self._get_connected(col, False)
|
1248
1305
|
for row in range(rows):
|
1306
|
+
connected_rows, _ = self._get_connected(row, False)
|
1249
1307
|
a = logical_index(row, col)
|
1250
1308
|
for c in connected_cols:
|
1251
|
-
for r in
|
1309
|
+
for r in connected_rows:
|
1252
1310
|
b = logical_index(r, c)
|
1253
1311
|
if a != b:
|
1254
1312
|
coupling_map.add((a, b))
|
@@ -1274,9 +1332,7 @@ class QrackAceBackend:
|
|
1274
1332
|
if is_long_a and is_long_b:
|
1275
1333
|
continue # No noise on long-to-long
|
1276
1334
|
|
1277
|
-
|
1278
|
-
|
1279
|
-
if same_col:
|
1335
|
+
if (col_a == col_b) or (row_a == row_b):
|
1280
1336
|
continue # No noise for same column
|
1281
1337
|
|
1282
1338
|
if is_long_a or is_long_b:
|
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
|