pyqrack-complex128 1.61.2__py3-none-manylinux_2_35_x86_64.whl → 1.82.1__py3-none-manylinux_2_35_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyqrack-complex128 might be problematic. Click here for more details.
- pyqrack/__init__.py +2 -2
- pyqrack/qrack_ace_backend.py +86 -81
- pyqrack/qrack_circuit.py +51 -40
- pyqrack/qrack_neuron.py +153 -34
- pyqrack/qrack_neuron_torch_layer.py +198 -107
- pyqrack/qrack_simulator.py +405 -371
- pyqrack/qrack_system/qrack_cl_precompile/qrack_cl_precompile +0 -0
- pyqrack/qrack_system/qrack_lib/libqrack_pinvoke.so +0 -0
- pyqrack/qrack_system/qrack_lib/libqrack_pinvoke.so.10.0.1 +0 -0
- pyqrack/qrack_system/qrack_system.py +87 -59
- pyqrack/stats/load_quantized_data.py +1 -3
- pyqrack/stats/quantize_by_range.py +2 -6
- {pyqrack_complex128-1.61.2.dist-info → pyqrack_complex128-1.82.1.dist-info}/METADATA +5 -5
- pyqrack_complex128-1.82.1.dist-info/RECORD +23 -0
- pyqrack/qrack_system/qrack_lib/libqrack_pinvoke.so.9.22.0 +0 -0
- pyqrack_complex128-1.61.2.dist-info/RECORD +0 -23
- {pyqrack_complex128-1.61.2.dist-info → pyqrack_complex128-1.82.1.dist-info}/LICENSE +0 -0
- {pyqrack_complex128-1.61.2.dist-info → pyqrack_complex128-1.82.1.dist-info}/WHEEL +0 -0
- {pyqrack_complex128-1.61.2.dist-info → pyqrack_complex128-1.82.1.dist-info}/top_level.txt +0 -0
pyqrack/__init__.py
CHANGED
|
@@ -10,8 +10,8 @@ from .qrack_ace_backend import QrackAceBackend
|
|
|
10
10
|
from .qrack_circuit import QrackCircuit
|
|
11
11
|
from .qrack_neuron import QrackNeuron
|
|
12
12
|
from .qrack_neuron_torch_layer import (
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
QrackNeuronTorch,
|
|
14
|
+
QrackNeuronTorchFunction,
|
|
15
15
|
QrackNeuronTorchLayer,
|
|
16
16
|
)
|
|
17
17
|
from .qrack_simulator import QrackSimulator
|
pyqrack/qrack_ace_backend.py
CHANGED
|
@@ -139,6 +139,12 @@ class LHVQubit:
|
|
|
139
139
|
new_y = 2 * (rho_prime[0][1].imag - rho_prime[1][0].imag)
|
|
140
140
|
new_z = 2 * rho_prime[0][0].real - 1 # since Tr(ρ') = 1
|
|
141
141
|
|
|
142
|
+
p = math.sqrt(new_x**2 + new_y**2 + new_z**2)
|
|
143
|
+
|
|
144
|
+
new_x /= p
|
|
145
|
+
new_y /= p
|
|
146
|
+
new_z /= p
|
|
147
|
+
|
|
142
148
|
self.bloch = [new_x, new_y, new_z]
|
|
143
149
|
|
|
144
150
|
def prob(self, basis=Pauli.PauliZ):
|
|
@@ -218,9 +224,7 @@ class QrackAceBackend:
|
|
|
218
224
|
isPaged=True,
|
|
219
225
|
isCpuGpuHybrid=True,
|
|
220
226
|
isOpenCL=True,
|
|
221
|
-
isHostPointer=(
|
|
222
|
-
True if os.environ.get("PYQRACK_HOST_POINTER_DEFAULT_ON") else False
|
|
223
|
-
),
|
|
227
|
+
isHostPointer=(True if os.environ.get("PYQRACK_HOST_POINTER_DEFAULT_ON") else False),
|
|
224
228
|
noise=0,
|
|
225
229
|
toClone=None,
|
|
226
230
|
):
|
|
@@ -273,7 +277,7 @@ class QrackAceBackend:
|
|
|
273
277
|
self._is_row_long_range[-1] = False
|
|
274
278
|
sim_count = col_patch_count * row_patch_count
|
|
275
279
|
|
|
276
|
-
self.
|
|
280
|
+
self._qubits = []
|
|
277
281
|
sim_counts = [0] * sim_count
|
|
278
282
|
sim_id = 0
|
|
279
283
|
tot_qubits = 0
|
|
@@ -288,11 +292,7 @@ class QrackAceBackend:
|
|
|
288
292
|
sim_counts[t_sim_id] += 1
|
|
289
293
|
|
|
290
294
|
qubit.append(
|
|
291
|
-
LHVQubit(
|
|
292
|
-
toClone=(
|
|
293
|
-
toClone._qubit_dict[tot_qubits][2] if toClone else None
|
|
294
|
-
)
|
|
295
|
-
)
|
|
295
|
+
LHVQubit(toClone=(toClone._qubits[tot_qubits][2] if toClone else None))
|
|
296
296
|
)
|
|
297
297
|
|
|
298
298
|
if (not c) and (not r):
|
|
@@ -307,7 +307,7 @@ class QrackAceBackend:
|
|
|
307
307
|
if not c:
|
|
308
308
|
sim_id = (sim_id + 1) % sim_count
|
|
309
309
|
|
|
310
|
-
self.
|
|
310
|
+
self._qubits.append(qubit)
|
|
311
311
|
tot_qubits += 1
|
|
312
312
|
|
|
313
313
|
self.sim = []
|
|
@@ -424,9 +424,10 @@ class QrackAceBackend:
|
|
|
424
424
|
self._qec_x(c)
|
|
425
425
|
|
|
426
426
|
def _unpack(self, lq):
|
|
427
|
-
return self.
|
|
427
|
+
return self._qubits[lq]
|
|
428
428
|
|
|
429
|
-
|
|
429
|
+
@staticmethod
|
|
430
|
+
def _get_qb_lhv_indices(hq):
|
|
430
431
|
qb = []
|
|
431
432
|
if len(hq) < 2:
|
|
432
433
|
qb = [0]
|
|
@@ -440,15 +441,16 @@ class QrackAceBackend:
|
|
|
440
441
|
|
|
441
442
|
return qb, lhv
|
|
442
443
|
|
|
443
|
-
|
|
444
|
+
@staticmethod
|
|
445
|
+
def _get_lhv_bloch_angles(sim):
|
|
444
446
|
# Z axis
|
|
445
|
-
z =
|
|
447
|
+
z = sim.bloch[2]
|
|
446
448
|
|
|
447
449
|
# X axis
|
|
448
|
-
x =
|
|
450
|
+
x = sim.bloch[0]
|
|
449
451
|
|
|
450
452
|
# Y axis
|
|
451
|
-
y =
|
|
453
|
+
y = sim.bloch[1]
|
|
452
454
|
|
|
453
455
|
inclination = math.atan2(math.sqrt(x**2 + y**2), z)
|
|
454
456
|
azimuth = math.atan2(y, x)
|
|
@@ -480,9 +482,7 @@ class QrackAceBackend:
|
|
|
480
482
|
|
|
481
483
|
return azimuth, inclination
|
|
482
484
|
|
|
483
|
-
def _rotate_to_bloch(
|
|
484
|
-
self, hq, delta_azimuth, delta_inclination
|
|
485
|
-
):
|
|
485
|
+
def _rotate_to_bloch(self, hq, delta_azimuth, delta_inclination):
|
|
486
486
|
sim = self.sim[hq[0]]
|
|
487
487
|
q = hq[1]
|
|
488
488
|
|
|
@@ -499,10 +499,8 @@ class QrackAceBackend:
|
|
|
499
499
|
|
|
500
500
|
sim.mtrx([m00, m01, m10, m11], q)
|
|
501
501
|
|
|
502
|
-
|
|
503
|
-
def _rotate_lhv_to_bloch(
|
|
504
|
-
self, sim, delta_azimuth, delta_inclination
|
|
505
|
-
):
|
|
502
|
+
@staticmethod
|
|
503
|
+
def _rotate_lhv_to_bloch(sim, delta_azimuth, delta_inclination):
|
|
506
504
|
# Apply rotation as "Azimuth, Inclination" (AI)
|
|
507
505
|
cosA = math.cos(delta_azimuth)
|
|
508
506
|
sinA = math.sin(delta_azimuth)
|
|
@@ -516,14 +514,13 @@ class QrackAceBackend:
|
|
|
516
514
|
|
|
517
515
|
sim.mtrx([m00, m01, m10, m11])
|
|
518
516
|
|
|
519
|
-
|
|
520
517
|
def _correct(self, lq, phase=False, skip_rotation=False):
|
|
521
518
|
hq = self._unpack(lq)
|
|
522
519
|
|
|
523
520
|
if len(hq) == 1:
|
|
524
521
|
return
|
|
525
522
|
|
|
526
|
-
qb, lhv =
|
|
523
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
527
524
|
|
|
528
525
|
if phase:
|
|
529
526
|
for q in qb:
|
|
@@ -542,9 +539,7 @@ class QrackAceBackend:
|
|
|
542
539
|
self.sim[hq[4][0]].prob(hq[4][1]),
|
|
543
540
|
]
|
|
544
541
|
# Balancing suggestion from Elara (the custom OpenAI GPT)
|
|
545
|
-
prms = math.sqrt(
|
|
546
|
-
(p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7
|
|
547
|
-
)
|
|
542
|
+
prms = math.sqrt((p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7)
|
|
548
543
|
qrms = math.sqrt(
|
|
549
544
|
(
|
|
550
545
|
(1 - p[0]) ** 2
|
|
@@ -572,13 +567,15 @@ class QrackAceBackend:
|
|
|
572
567
|
a, i = [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]
|
|
573
568
|
a[0], i[0] = self._get_bloch_angles(hq[0])
|
|
574
569
|
a[1], i[1] = self._get_bloch_angles(hq[1])
|
|
575
|
-
a[2], i[2] =
|
|
570
|
+
a[2], i[2] = QrackAceBackend._get_lhv_bloch_angles(hq[2])
|
|
576
571
|
a[3], i[3] = self._get_bloch_angles(hq[3])
|
|
577
572
|
a[4], i[4] = self._get_bloch_angles(hq[4])
|
|
578
573
|
|
|
579
574
|
a_target = 0
|
|
580
575
|
i_target = 0
|
|
581
576
|
for x in range(5):
|
|
577
|
+
if x == 2:
|
|
578
|
+
continue
|
|
582
579
|
a_target += a[x]
|
|
583
580
|
i_target += i[x]
|
|
584
581
|
|
|
@@ -586,7 +583,9 @@ class QrackAceBackend:
|
|
|
586
583
|
i_target /= 5
|
|
587
584
|
for x in range(5):
|
|
588
585
|
if x == 2:
|
|
589
|
-
|
|
586
|
+
QrackAceBackend._rotate_lhv_to_bloch(
|
|
587
|
+
hq[x], a_target - a[x], i_target - i[x]
|
|
588
|
+
)
|
|
590
589
|
else:
|
|
591
590
|
self._rotate_to_bloch(hq[x], a_target - a[x], i_target - i[x])
|
|
592
591
|
|
|
@@ -613,11 +612,13 @@ class QrackAceBackend:
|
|
|
613
612
|
a, i = [0, 0, 0], [0, 0, 0]
|
|
614
613
|
a[0], i[0] = self._get_bloch_angles(hq[0])
|
|
615
614
|
a[1], i[1] = self._get_bloch_angles(hq[1])
|
|
616
|
-
a[2], i[2] =
|
|
615
|
+
a[2], i[2] = QrackAceBackend._get_lhv_bloch_angles(hq[2])
|
|
617
616
|
|
|
618
617
|
a_target = 0
|
|
619
618
|
i_target = 0
|
|
620
619
|
for x in range(3):
|
|
620
|
+
if x == 2:
|
|
621
|
+
continue
|
|
621
622
|
a_target += a[x]
|
|
622
623
|
i_target += i[x]
|
|
623
624
|
|
|
@@ -625,7 +626,9 @@ class QrackAceBackend:
|
|
|
625
626
|
i_target /= 3
|
|
626
627
|
for x in range(3):
|
|
627
628
|
if x == 2:
|
|
628
|
-
|
|
629
|
+
QrackAceBackend._rotate_lhv_to_bloch(
|
|
630
|
+
hq[x], a_target - a[x], i_target - i[x]
|
|
631
|
+
)
|
|
629
632
|
else:
|
|
630
633
|
self._rotate_to_bloch(hq[x], a_target - a[x], i_target - i[x])
|
|
631
634
|
|
|
@@ -636,6 +639,29 @@ class QrackAceBackend:
|
|
|
636
639
|
b = hq[lhv]
|
|
637
640
|
b.h()
|
|
638
641
|
|
|
642
|
+
def apply_magnetic_bias(self, q, b):
|
|
643
|
+
if b == 0:
|
|
644
|
+
return
|
|
645
|
+
b = math.exp(b)
|
|
646
|
+
for x in q:
|
|
647
|
+
hq = self._unpack(x)
|
|
648
|
+
for c in range(len(hq)):
|
|
649
|
+
h = hq[c]
|
|
650
|
+
if c == 2:
|
|
651
|
+
a, i = QrackAceBackend._get_lhv_bloch_angles(h)
|
|
652
|
+
QrackAceBackend._rotate_lhv_to_bloch(
|
|
653
|
+
h,
|
|
654
|
+
math.atan(math.tan(a) * b) - a,
|
|
655
|
+
math.atan(math.tan(i) * b) - i,
|
|
656
|
+
)
|
|
657
|
+
else:
|
|
658
|
+
a, i = self._get_bloch_angles(h)
|
|
659
|
+
self._rotate_to_bloch(
|
|
660
|
+
h,
|
|
661
|
+
math.atan(math.tan(a) * b) - a,
|
|
662
|
+
math.atan(math.tan(i) * b) - i,
|
|
663
|
+
)
|
|
664
|
+
|
|
639
665
|
def u(self, lq, th, ph, lm):
|
|
640
666
|
hq = self._unpack(lq)
|
|
641
667
|
if len(hq) < 2:
|
|
@@ -643,7 +669,7 @@ class QrackAceBackend:
|
|
|
643
669
|
self.sim[b[0]].u(b[1], th, ph, lm)
|
|
644
670
|
return
|
|
645
671
|
|
|
646
|
-
qb, lhv =
|
|
672
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
647
673
|
|
|
648
674
|
for q in qb:
|
|
649
675
|
b = hq[q]
|
|
@@ -662,7 +688,7 @@ class QrackAceBackend:
|
|
|
662
688
|
self.sim[b[0]].r(p, th, b[1])
|
|
663
689
|
return
|
|
664
690
|
|
|
665
|
-
qb, lhv =
|
|
691
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
666
692
|
|
|
667
693
|
for q in qb:
|
|
668
694
|
b = hq[q]
|
|
@@ -690,7 +716,7 @@ class QrackAceBackend:
|
|
|
690
716
|
|
|
691
717
|
self._correct(lq)
|
|
692
718
|
|
|
693
|
-
qb, lhv =
|
|
719
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
694
720
|
|
|
695
721
|
for q in qb:
|
|
696
722
|
b = hq[q]
|
|
@@ -708,7 +734,7 @@ class QrackAceBackend:
|
|
|
708
734
|
self.sim[b[0]].s(b[1])
|
|
709
735
|
return
|
|
710
736
|
|
|
711
|
-
qb, lhv =
|
|
737
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
712
738
|
|
|
713
739
|
for q in qb:
|
|
714
740
|
b = hq[q]
|
|
@@ -724,7 +750,7 @@ class QrackAceBackend:
|
|
|
724
750
|
self.sim[b[0]].adjs(b[1])
|
|
725
751
|
return
|
|
726
752
|
|
|
727
|
-
qb, lhv =
|
|
753
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
728
754
|
|
|
729
755
|
for q in qb:
|
|
730
756
|
b = hq[q]
|
|
@@ -740,7 +766,7 @@ class QrackAceBackend:
|
|
|
740
766
|
self.sim[b[0]].x(b[1])
|
|
741
767
|
return
|
|
742
768
|
|
|
743
|
-
qb, lhv =
|
|
769
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
744
770
|
|
|
745
771
|
for q in qb:
|
|
746
772
|
b = hq[q]
|
|
@@ -756,7 +782,7 @@ class QrackAceBackend:
|
|
|
756
782
|
self.sim[b[0]].y(b[1])
|
|
757
783
|
return
|
|
758
784
|
|
|
759
|
-
qb, lhv =
|
|
785
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
760
786
|
|
|
761
787
|
for q in qb:
|
|
762
788
|
b = hq[q]
|
|
@@ -772,7 +798,7 @@ class QrackAceBackend:
|
|
|
772
798
|
self.sim[b[0]].z(b[1])
|
|
773
799
|
return
|
|
774
800
|
|
|
775
|
-
qb, lhv =
|
|
801
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
776
802
|
|
|
777
803
|
for q in qb:
|
|
778
804
|
b = hq[q]
|
|
@@ -788,7 +814,7 @@ class QrackAceBackend:
|
|
|
788
814
|
self.sim[b[0]].t(b[1])
|
|
789
815
|
return
|
|
790
816
|
|
|
791
|
-
qb, lhv =
|
|
817
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
792
818
|
|
|
793
819
|
for q in qb:
|
|
794
820
|
b = hq[q]
|
|
@@ -804,7 +830,7 @@ class QrackAceBackend:
|
|
|
804
830
|
self.sim[b[0]].adjt(b[1])
|
|
805
831
|
return
|
|
806
832
|
|
|
807
|
-
qb, lhv =
|
|
833
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
808
834
|
|
|
809
835
|
for q in qb:
|
|
810
836
|
b = hq[q]
|
|
@@ -826,9 +852,7 @@ class QrackAceBackend:
|
|
|
826
852
|
gate = self.sim[sim_id].macz if anti else self.sim[sim_id].mcz
|
|
827
853
|
shadow = self._anti_cz_shadow if anti else self._cz_shadow
|
|
828
854
|
else:
|
|
829
|
-
raise RuntimeError(
|
|
830
|
-
"QrackAceBackend._get_gate() should never return identity!"
|
|
831
|
-
)
|
|
855
|
+
raise RuntimeError("QrackAceBackend._get_gate() should never return identity!")
|
|
832
856
|
|
|
833
857
|
return gate, shadow
|
|
834
858
|
|
|
@@ -865,11 +889,7 @@ class QrackAceBackend:
|
|
|
865
889
|
b2 = hq2[q2]
|
|
866
890
|
if b1[0] == b2[0]:
|
|
867
891
|
gate_fn([b1[1]], b2[1])
|
|
868
|
-
elif (
|
|
869
|
-
lq1_lr
|
|
870
|
-
or (b1[1] == b2[1])
|
|
871
|
-
or ((len(qb1) == 2) and (b1[1] == (b2[1] & 1)))
|
|
872
|
-
):
|
|
892
|
+
elif lq1_lr or (b1[1] == b2[1]) or ((len(qb1) == 2) and (b1[1] == (b2[1] & 1))):
|
|
873
893
|
shadow_fn(b1, b2)
|
|
874
894
|
|
|
875
895
|
def _cpauli(self, lq1, lq2, anti, pauli):
|
|
@@ -886,8 +906,8 @@ class QrackAceBackend:
|
|
|
886
906
|
|
|
887
907
|
self._correct(lq1)
|
|
888
908
|
|
|
889
|
-
qb1, lhv1 =
|
|
890
|
-
qb2, lhv2 =
|
|
909
|
+
qb1, lhv1 = QrackAceBackend._get_qb_lhv_indices(hq1)
|
|
910
|
+
qb2, lhv2 = QrackAceBackend._get_qb_lhv_indices(hq2)
|
|
891
911
|
# Apply cross coupling on hardware qubits first
|
|
892
912
|
self._apply_coupling(pauli, anti, qb1, lhv1, hq1, qb2, lhv2, hq2, lq1_lr)
|
|
893
913
|
# Apply coupling to the local-hidden-variable target
|
|
@@ -999,9 +1019,7 @@ class QrackAceBackend:
|
|
|
999
1019
|
self.sim[hq[4][0]].prob(hq[4][1]),
|
|
1000
1020
|
]
|
|
1001
1021
|
# Balancing suggestion from Elara (the custom OpenAI GPT)
|
|
1002
|
-
prms = math.sqrt(
|
|
1003
|
-
(p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7
|
|
1004
|
-
)
|
|
1022
|
+
prms = math.sqrt((p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7)
|
|
1005
1023
|
qrms = math.sqrt(
|
|
1006
1024
|
(
|
|
1007
1025
|
(1 - p[0]) ** 2
|
|
@@ -1034,7 +1052,7 @@ class QrackAceBackend:
|
|
|
1034
1052
|
p = self.prob(lq)
|
|
1035
1053
|
result = ((p + self._epsilon) >= 1) or (random.random() < p)
|
|
1036
1054
|
|
|
1037
|
-
qb, lhv =
|
|
1055
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
1038
1056
|
|
|
1039
1057
|
for q in qb:
|
|
1040
1058
|
b = hq[q]
|
|
@@ -1060,7 +1078,7 @@ class QrackAceBackend:
|
|
|
1060
1078
|
|
|
1061
1079
|
self._correct(lq)
|
|
1062
1080
|
|
|
1063
|
-
qb, lhv =
|
|
1081
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
1064
1082
|
|
|
1065
1083
|
for q in qb:
|
|
1066
1084
|
b = hq[q]
|
|
@@ -1153,17 +1171,11 @@ class QrackAceBackend:
|
|
|
1153
1171
|
(-1 * float(operation.params[1])) + math.pi / 2,
|
|
1154
1172
|
)
|
|
1155
1173
|
elif name == "rx":
|
|
1156
|
-
self._sim.r(
|
|
1157
|
-
Pauli.PauliX, float(operation.params[0]), operation.qubits[0]._index
|
|
1158
|
-
)
|
|
1174
|
+
self._sim.r(Pauli.PauliX, float(operation.params[0]), operation.qubits[0]._index)
|
|
1159
1175
|
elif name == "ry":
|
|
1160
|
-
self._sim.r(
|
|
1161
|
-
Pauli.PauliY, float(operation.params[0]), operation.qubits[0]._index
|
|
1162
|
-
)
|
|
1176
|
+
self._sim.r(Pauli.PauliY, float(operation.params[0]), operation.qubits[0]._index)
|
|
1163
1177
|
elif name == "rz":
|
|
1164
|
-
self._sim.r(
|
|
1165
|
-
Pauli.PauliZ, float(operation.params[0]), operation.qubits[0]._index
|
|
1166
|
-
)
|
|
1178
|
+
self._sim.r(Pauli.PauliZ, float(operation.params[0]), operation.qubits[0]._index)
|
|
1167
1179
|
elif name == "h":
|
|
1168
1180
|
self._sim.h(operation.qubits[0]._index)
|
|
1169
1181
|
elif name == "x":
|
|
@@ -1228,9 +1240,9 @@ class QrackAceBackend:
|
|
|
1228
1240
|
cregbit = clbit
|
|
1229
1241
|
|
|
1230
1242
|
regbit = 1 << cregbit
|
|
1231
|
-
self._classical_register = (
|
|
1232
|
-
|
|
1233
|
-
)
|
|
1243
|
+
self._classical_register = (self._classical_register & (~regbit)) | (
|
|
1244
|
+
qubit_outcome << cregbit
|
|
1245
|
+
)
|
|
1234
1246
|
|
|
1235
1247
|
elif name == "bfunc":
|
|
1236
1248
|
mask = int(operation.mask, 16)
|
|
@@ -1345,9 +1357,7 @@ class QrackAceBackend:
|
|
|
1345
1357
|
if operation.name == "id" or operation.name == "barrier":
|
|
1346
1358
|
continue
|
|
1347
1359
|
|
|
1348
|
-
if is_initializing and (
|
|
1349
|
-
(operation.name == "measure") or (operation.name == "reset")
|
|
1350
|
-
):
|
|
1360
|
+
if is_initializing and ((operation.name == "measure") or (operation.name == "reset")):
|
|
1351
1361
|
continue
|
|
1352
1362
|
|
|
1353
1363
|
is_initializing = False
|
|
@@ -1405,14 +1415,13 @@ class QrackAceBackend:
|
|
|
1405
1415
|
self._sample_cregbits = []
|
|
1406
1416
|
|
|
1407
1417
|
if self._sample_measure and (len(self._sample_qubits) > 0):
|
|
1408
|
-
_data = self._add_sample_measure(
|
|
1409
|
-
self._sample_qubits, self._sample_clbits, self._shots
|
|
1410
|
-
)
|
|
1418
|
+
_data = self._add_sample_measure(self._sample_qubits, self._sample_clbits, self._shots)
|
|
1411
1419
|
|
|
1412
1420
|
del self._sim
|
|
1413
1421
|
|
|
1414
1422
|
return _data
|
|
1415
1423
|
|
|
1424
|
+
@staticmethod
|
|
1416
1425
|
def get_qiskit_basis_gates():
|
|
1417
1426
|
return [
|
|
1418
1427
|
"id",
|
|
@@ -1497,17 +1506,13 @@ class QrackAceBackend:
|
|
|
1497
1506
|
noise_model.add_quantum_error(depolarizing_error(y, 2), "cx", [a, b])
|
|
1498
1507
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
|
|
1499
1508
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
|
|
1500
|
-
noise_model.add_quantum_error(
|
|
1501
|
-
depolarizing_error(y_swap, 2), "swap", [a, b]
|
|
1502
|
-
)
|
|
1509
|
+
noise_model.add_quantum_error(depolarizing_error(y_swap, 2), "swap", [a, b])
|
|
1503
1510
|
else:
|
|
1504
1511
|
y_cy = 1 - (1 - y) ** 2
|
|
1505
1512
|
y_swap = 1 - (1 - y) ** 3
|
|
1506
1513
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cx", [a, b])
|
|
1507
1514
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
|
|
1508
1515
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
|
|
1509
|
-
noise_model.add_quantum_error(
|
|
1510
|
-
depolarizing_error(y_swap, 2), "swap", [a, b]
|
|
1511
|
-
)
|
|
1516
|
+
noise_model.add_quantum_error(depolarizing_error(y_swap, 2), "swap", [a, b])
|
|
1512
1517
|
|
|
1513
1518
|
return noise_model
|
pyqrack/qrack_circuit.py
CHANGED
|
@@ -59,7 +59,7 @@ class QrackCircuit:
|
|
|
59
59
|
self.cid = Qrack.qrack_lib.qcircuit_inverse(clone_cid)
|
|
60
60
|
elif len(past_light_cone) > 0:
|
|
61
61
|
self.cid = Qrack.qrack_lib.qcircuit_past_light_cone(
|
|
62
|
-
clone_cid, len(past_light_cone),
|
|
62
|
+
clone_cid, len(past_light_cone), QrackCircuit._ulonglong_byref(past_light_cone)
|
|
63
63
|
)
|
|
64
64
|
else:
|
|
65
65
|
self.cid = Qrack.qrack_lib.init_qcircuit_clone(clone_cid)
|
|
@@ -69,16 +69,20 @@ class QrackCircuit:
|
|
|
69
69
|
Qrack.qrack_lib.destroy_qcircuit(self.cid)
|
|
70
70
|
self.cid = None
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
@staticmethod
|
|
73
|
+
def _ulonglong_byref(a):
|
|
73
74
|
return (ctypes.c_ulonglong * len(a))(*a)
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
@staticmethod
|
|
77
|
+
def _double_byref(a):
|
|
76
78
|
return (ctypes.c_double * len(a))(*a)
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
@staticmethod
|
|
81
|
+
def _complex_byref(a):
|
|
79
82
|
t = [(c.real, c.imag) for c in a]
|
|
80
|
-
return
|
|
83
|
+
return QrackCircuit._double_byref([float(item) for sublist in t for item in sublist])
|
|
81
84
|
|
|
85
|
+
@staticmethod
|
|
82
86
|
def _mtrx_to_u4(m):
|
|
83
87
|
nrm = abs(m[0])
|
|
84
88
|
if (nrm * nrm) < sys.float_info.epsilon:
|
|
@@ -103,6 +107,7 @@ class QrackCircuit:
|
|
|
103
107
|
|
|
104
108
|
return th, ph, lm, np.angle(phase)
|
|
105
109
|
|
|
110
|
+
@staticmethod
|
|
106
111
|
def _u3_to_mtrx(params):
|
|
107
112
|
th = float(params[0])
|
|
108
113
|
ph = float(params[1])
|
|
@@ -115,6 +120,7 @@ class QrackCircuit:
|
|
|
115
120
|
|
|
116
121
|
return [c + 0j, -el * s, ep * s, ep * el * c]
|
|
117
122
|
|
|
123
|
+
@staticmethod
|
|
118
124
|
def _u4_to_mtrx(params):
|
|
119
125
|
m = QrackCircuit._u3_to_mtrx(params)
|
|
120
126
|
g = np.exp(1j * float(params[3]))
|
|
@@ -123,6 +129,7 @@ class QrackCircuit:
|
|
|
123
129
|
|
|
124
130
|
return m
|
|
125
131
|
|
|
132
|
+
@staticmethod
|
|
126
133
|
def _make_mtrx_unitary(m):
|
|
127
134
|
return QrackCircuit._u4_to_mtrx(QrackCircuit._mtrx_to_u4(m))
|
|
128
135
|
|
|
@@ -190,7 +197,7 @@ class QrackCircuit:
|
|
|
190
197
|
raise ValueError(
|
|
191
198
|
"2x2 matrix 'm' in QrackCircuit.mtrx() must contain at least 4 elements."
|
|
192
199
|
)
|
|
193
|
-
Qrack.qrack_lib.qcircuit_append_1qb(self.cid,
|
|
200
|
+
Qrack.qrack_lib.qcircuit_append_1qb(self.cid, QrackCircuit._complex_byref(m), q)
|
|
194
201
|
|
|
195
202
|
def ucmtrx(self, c, m, q, p):
|
|
196
203
|
"""Multi-controlled single-target-qubit gate
|
|
@@ -214,7 +221,7 @@ class QrackCircuit:
|
|
|
214
221
|
"2x2 matrix 'm' in QrackCircuit.ucmtrx() must contain at least 4 elements."
|
|
215
222
|
)
|
|
216
223
|
Qrack.qrack_lib.qcircuit_append_mc(
|
|
217
|
-
self.cid,
|
|
224
|
+
self.cid, QrackCircuit._complex_byref(m), len(c), QrackCircuit._ulonglong_byref(c), q, p
|
|
218
225
|
)
|
|
219
226
|
|
|
220
227
|
def run(self, qsim):
|
|
@@ -248,20 +255,6 @@ class QrackCircuit:
|
|
|
248
255
|
"""
|
|
249
256
|
Qrack.qrack_lib.qcircuit_out_to_file(self.cid, filename.encode("utf-8"))
|
|
250
257
|
|
|
251
|
-
def in_from_file(filename):
|
|
252
|
-
"""Read in optimized circuit from file
|
|
253
|
-
|
|
254
|
-
Reads in an (optimized) circuit from a file named
|
|
255
|
-
according to the "filename" parameter.
|
|
256
|
-
|
|
257
|
-
Args:
|
|
258
|
-
filename: Name of file
|
|
259
|
-
"""
|
|
260
|
-
out = QrackCircuit()
|
|
261
|
-
Qrack.qrack_lib.qcircuit_in_from_file(out.cid, filename.encode("utf-8"))
|
|
262
|
-
|
|
263
|
-
return out
|
|
264
|
-
|
|
265
258
|
def out_to_string(self):
|
|
266
259
|
"""Output optimized circuit to string
|
|
267
260
|
|
|
@@ -273,19 +266,6 @@ class QrackCircuit:
|
|
|
273
266
|
|
|
274
267
|
return out.value.decode("utf-8")
|
|
275
268
|
|
|
276
|
-
def file_gate_count(filename):
|
|
277
|
-
"""File gate count
|
|
278
|
-
|
|
279
|
-
Return the count of gates in a QrackCircuit file
|
|
280
|
-
|
|
281
|
-
Args:
|
|
282
|
-
filename: Name of file
|
|
283
|
-
"""
|
|
284
|
-
tokens = []
|
|
285
|
-
with open(filename, "r") as file:
|
|
286
|
-
tokens = file.read().split()
|
|
287
|
-
return int(tokens[1])
|
|
288
|
-
|
|
289
269
|
def to_qiskit_circuit(self):
|
|
290
270
|
"""Convert to a Qiskit circuit
|
|
291
271
|
|
|
@@ -302,6 +282,36 @@ class QrackCircuit:
|
|
|
302
282
|
|
|
303
283
|
return QrackCircuit.string_to_qiskit_circuit(self.out_to_string())
|
|
304
284
|
|
|
285
|
+
@staticmethod
|
|
286
|
+
def in_from_file(filename):
|
|
287
|
+
"""Read in optimized circuit from file
|
|
288
|
+
|
|
289
|
+
Reads in an (optimized) circuit from a file named
|
|
290
|
+
according to the "filename" parameter.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
filename: Name of file
|
|
294
|
+
"""
|
|
295
|
+
out = QrackCircuit()
|
|
296
|
+
Qrack.qrack_lib.qcircuit_in_from_file(out.cid, filename.encode("utf-8"))
|
|
297
|
+
|
|
298
|
+
return out
|
|
299
|
+
|
|
300
|
+
@staticmethod
|
|
301
|
+
def file_gate_count(filename):
|
|
302
|
+
"""File gate count
|
|
303
|
+
|
|
304
|
+
Return the count of gates in a QrackCircuit file
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
filename: Name of file
|
|
308
|
+
"""
|
|
309
|
+
tokens = []
|
|
310
|
+
with open(filename, "r") as file:
|
|
311
|
+
tokens = file.read().split()
|
|
312
|
+
return int(tokens[1])
|
|
313
|
+
|
|
314
|
+
@staticmethod
|
|
305
315
|
def file_to_qiskit_circuit(filename):
|
|
306
316
|
"""Convert an output file to a Qiskit circuit
|
|
307
317
|
|
|
@@ -325,6 +335,7 @@ class QrackCircuit:
|
|
|
325
335
|
with open(filename, "r") as file:
|
|
326
336
|
return QrackCircuit.string_to_qiskit_circuit(file.read())
|
|
327
337
|
|
|
338
|
+
@staticmethod
|
|
328
339
|
def string_to_qiskit_circuit(circ_string):
|
|
329
340
|
"""Convert an output string to a Qiskit circuit
|
|
330
341
|
|
|
@@ -398,6 +409,7 @@ class QrackCircuit:
|
|
|
398
409
|
|
|
399
410
|
return circ
|
|
400
411
|
|
|
412
|
+
@staticmethod
|
|
401
413
|
def in_from_qiskit_circuit(circ):
|
|
402
414
|
"""Read a Qiskit circuit into a QrackCircuit
|
|
403
415
|
|
|
@@ -443,6 +455,7 @@ class QrackCircuit:
|
|
|
443
455
|
|
|
444
456
|
return out
|
|
445
457
|
|
|
458
|
+
@staticmethod
|
|
446
459
|
def file_to_quimb_circuit(
|
|
447
460
|
filename,
|
|
448
461
|
circuit_type=QuimbCircuitType.Circuit,
|
|
@@ -494,9 +507,7 @@ class QrackCircuit:
|
|
|
494
507
|
)
|
|
495
508
|
if circuit_type == QuimbCircuitType.Circuit
|
|
496
509
|
else (
|
|
497
|
-
qtn.CircuitDense(
|
|
498
|
-
N=qcirc.num_qubits, psi0=psi0, gate_opts=gate_opts, tags=tags
|
|
499
|
-
)
|
|
510
|
+
qtn.CircuitDense(N=qcirc.num_qubits, psi0=psi0, gate_opts=gate_opts, tags=tags)
|
|
500
511
|
if circuit_type == QuimbCircuitType.CircuitDense
|
|
501
512
|
else qtn.CircuitMPS(
|
|
502
513
|
N=qcirc.num_qubits,
|
|
@@ -526,9 +537,8 @@ class QrackCircuit:
|
|
|
526
537
|
|
|
527
538
|
return tcirc
|
|
528
539
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
):
|
|
540
|
+
@staticmethod
|
|
541
|
+
def file_to_tensorcircuit(filename, inputs=None, circuit_params=None, binding_params=None):
|
|
532
542
|
"""Convert an output file to a TensorCircuit circuit
|
|
533
543
|
|
|
534
544
|
Reads in an (optimized) circuit from a file named
|
|
@@ -558,6 +568,7 @@ class QrackCircuit:
|
|
|
558
568
|
qcirc, qcirc.num_qubits, inputs, circuit_params, binding_params
|
|
559
569
|
)
|
|
560
570
|
|
|
571
|
+
@staticmethod
|
|
561
572
|
def in_from_tensorcircuit(tcirc, enable_instruction=False, enable_inputs=False):
|
|
562
573
|
"""Convert a TensorCircuit circuit to a QrackCircuit
|
|
563
574
|
|