pyqrack-cpu 1.76.0__py3-none-macosx_14_0_arm64.whl → 1.80.3__py3-none-macosx_14_0_arm64.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.
- pyqrack/__init__.py +2 -2
- pyqrack/qrack_ace_backend.py +44 -70
- pyqrack/qrack_circuit.py +51 -40
- pyqrack/qrack_neuron.py +35 -10
- pyqrack/qrack_neuron_torch_layer.py +182 -106
- pyqrack/qrack_simulator.py +269 -271
- pyqrack/qrack_system/qrack_lib/{libqrack_pinvoke.9.34.5.dylib → libqrack_pinvoke.9.35.2.dylib} +0 -0
- pyqrack/qrack_system/qrack_lib/libqrack_pinvoke.dylib +0 -0
- pyqrack/qrack_system/qrack_system.py +19 -12
- pyqrack/stats/load_quantized_data.py +1 -3
- pyqrack/stats/quantize_by_range.py +2 -6
- {pyqrack_cpu-1.76.0.dist-info → pyqrack_cpu-1.80.3.dist-info}/METADATA +3 -3
- pyqrack_cpu-1.80.3.dist-info/RECORD +23 -0
- pyqrack_cpu-1.76.0.dist-info/RECORD +0 -23
- {pyqrack_cpu-1.76.0.dist-info → pyqrack_cpu-1.80.3.dist-info}/LICENSE +0 -0
- {pyqrack_cpu-1.76.0.dist-info → pyqrack_cpu-1.80.3.dist-info}/WHEEL +0 -0
- {pyqrack_cpu-1.76.0.dist-info → pyqrack_cpu-1.80.3.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
|
@@ -224,9 +224,7 @@ class QrackAceBackend:
|
|
|
224
224
|
isPaged=True,
|
|
225
225
|
isCpuGpuHybrid=True,
|
|
226
226
|
isOpenCL=True,
|
|
227
|
-
isHostPointer=(
|
|
228
|
-
True if os.environ.get("PYQRACK_HOST_POINTER_DEFAULT_ON") else False
|
|
229
|
-
),
|
|
227
|
+
isHostPointer=(True if os.environ.get("PYQRACK_HOST_POINTER_DEFAULT_ON") else False),
|
|
230
228
|
noise=0,
|
|
231
229
|
toClone=None,
|
|
232
230
|
):
|
|
@@ -294,11 +292,7 @@ class QrackAceBackend:
|
|
|
294
292
|
sim_counts[t_sim_id] += 1
|
|
295
293
|
|
|
296
294
|
qubit.append(
|
|
297
|
-
LHVQubit(
|
|
298
|
-
toClone=(
|
|
299
|
-
toClone._qubits[tot_qubits][2] if toClone else None
|
|
300
|
-
)
|
|
301
|
-
)
|
|
295
|
+
LHVQubit(toClone=(toClone._qubits[tot_qubits][2] if toClone else None))
|
|
302
296
|
)
|
|
303
297
|
|
|
304
298
|
if (not c) and (not r):
|
|
@@ -432,7 +426,8 @@ class QrackAceBackend:
|
|
|
432
426
|
def _unpack(self, lq):
|
|
433
427
|
return self._qubits[lq]
|
|
434
428
|
|
|
435
|
-
|
|
429
|
+
@staticmethod
|
|
430
|
+
def _get_qb_lhv_indices(hq):
|
|
436
431
|
qb = []
|
|
437
432
|
if len(hq) < 2:
|
|
438
433
|
qb = [0]
|
|
@@ -446,7 +441,8 @@ class QrackAceBackend:
|
|
|
446
441
|
|
|
447
442
|
return qb, lhv
|
|
448
443
|
|
|
449
|
-
|
|
444
|
+
@staticmethod
|
|
445
|
+
def _get_lhv_bloch_angles(sim):
|
|
450
446
|
# Z axis
|
|
451
447
|
z = sim.bloch[2]
|
|
452
448
|
|
|
@@ -503,7 +499,8 @@ class QrackAceBackend:
|
|
|
503
499
|
|
|
504
500
|
sim.mtrx([m00, m01, m10, m11], q)
|
|
505
501
|
|
|
506
|
-
|
|
502
|
+
@staticmethod
|
|
503
|
+
def _rotate_lhv_to_bloch(sim, delta_azimuth, delta_inclination):
|
|
507
504
|
# Apply rotation as "Azimuth, Inclination" (AI)
|
|
508
505
|
cosA = math.cos(delta_azimuth)
|
|
509
506
|
sinA = math.sin(delta_azimuth)
|
|
@@ -523,7 +520,7 @@ class QrackAceBackend:
|
|
|
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,7 +567,7 @@ 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
|
|
|
@@ -588,7 +583,7 @@ class QrackAceBackend:
|
|
|
588
583
|
i_target /= 5
|
|
589
584
|
for x in range(5):
|
|
590
585
|
if x == 2:
|
|
591
|
-
|
|
586
|
+
QrackAceBackend._rotate_lhv_to_bloch(
|
|
592
587
|
hq[x], a_target - a[x], i_target - i[x]
|
|
593
588
|
)
|
|
594
589
|
else:
|
|
@@ -617,7 +612,7 @@ class QrackAceBackend:
|
|
|
617
612
|
a, i = [0, 0, 0], [0, 0, 0]
|
|
618
613
|
a[0], i[0] = self._get_bloch_angles(hq[0])
|
|
619
614
|
a[1], i[1] = self._get_bloch_angles(hq[1])
|
|
620
|
-
a[2], i[2] =
|
|
615
|
+
a[2], i[2] = QrackAceBackend._get_lhv_bloch_angles(hq[2])
|
|
621
616
|
|
|
622
617
|
a_target = 0
|
|
623
618
|
i_target = 0
|
|
@@ -631,7 +626,7 @@ class QrackAceBackend:
|
|
|
631
626
|
i_target /= 3
|
|
632
627
|
for x in range(3):
|
|
633
628
|
if x == 2:
|
|
634
|
-
|
|
629
|
+
QrackAceBackend._rotate_lhv_to_bloch(
|
|
635
630
|
hq[x], a_target - a[x], i_target - i[x]
|
|
636
631
|
)
|
|
637
632
|
else:
|
|
@@ -653,8 +648,8 @@ class QrackAceBackend:
|
|
|
653
648
|
for c in range(len(hq)):
|
|
654
649
|
h = hq[c]
|
|
655
650
|
if c == 2:
|
|
656
|
-
a, i =
|
|
657
|
-
|
|
651
|
+
a, i = QrackAceBackend._get_lhv_bloch_angles(h)
|
|
652
|
+
QrackAceBackend._rotate_lhv_to_bloch(
|
|
658
653
|
h,
|
|
659
654
|
math.atan(math.tan(a) * b) - a,
|
|
660
655
|
math.atan(math.tan(i) * b) - i,
|
|
@@ -674,7 +669,7 @@ class QrackAceBackend:
|
|
|
674
669
|
self.sim[b[0]].u(b[1], th, ph, lm)
|
|
675
670
|
return
|
|
676
671
|
|
|
677
|
-
qb, lhv =
|
|
672
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
678
673
|
|
|
679
674
|
for q in qb:
|
|
680
675
|
b = hq[q]
|
|
@@ -693,7 +688,7 @@ class QrackAceBackend:
|
|
|
693
688
|
self.sim[b[0]].r(p, th, b[1])
|
|
694
689
|
return
|
|
695
690
|
|
|
696
|
-
qb, lhv =
|
|
691
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
697
692
|
|
|
698
693
|
for q in qb:
|
|
699
694
|
b = hq[q]
|
|
@@ -721,7 +716,7 @@ class QrackAceBackend:
|
|
|
721
716
|
|
|
722
717
|
self._correct(lq)
|
|
723
718
|
|
|
724
|
-
qb, lhv =
|
|
719
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
725
720
|
|
|
726
721
|
for q in qb:
|
|
727
722
|
b = hq[q]
|
|
@@ -739,7 +734,7 @@ class QrackAceBackend:
|
|
|
739
734
|
self.sim[b[0]].s(b[1])
|
|
740
735
|
return
|
|
741
736
|
|
|
742
|
-
qb, lhv =
|
|
737
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
743
738
|
|
|
744
739
|
for q in qb:
|
|
745
740
|
b = hq[q]
|
|
@@ -755,7 +750,7 @@ class QrackAceBackend:
|
|
|
755
750
|
self.sim[b[0]].adjs(b[1])
|
|
756
751
|
return
|
|
757
752
|
|
|
758
|
-
qb, lhv =
|
|
753
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
759
754
|
|
|
760
755
|
for q in qb:
|
|
761
756
|
b = hq[q]
|
|
@@ -771,7 +766,7 @@ class QrackAceBackend:
|
|
|
771
766
|
self.sim[b[0]].x(b[1])
|
|
772
767
|
return
|
|
773
768
|
|
|
774
|
-
qb, lhv =
|
|
769
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
775
770
|
|
|
776
771
|
for q in qb:
|
|
777
772
|
b = hq[q]
|
|
@@ -787,7 +782,7 @@ class QrackAceBackend:
|
|
|
787
782
|
self.sim[b[0]].y(b[1])
|
|
788
783
|
return
|
|
789
784
|
|
|
790
|
-
qb, lhv =
|
|
785
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
791
786
|
|
|
792
787
|
for q in qb:
|
|
793
788
|
b = hq[q]
|
|
@@ -803,7 +798,7 @@ class QrackAceBackend:
|
|
|
803
798
|
self.sim[b[0]].z(b[1])
|
|
804
799
|
return
|
|
805
800
|
|
|
806
|
-
qb, lhv =
|
|
801
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
807
802
|
|
|
808
803
|
for q in qb:
|
|
809
804
|
b = hq[q]
|
|
@@ -819,7 +814,7 @@ class QrackAceBackend:
|
|
|
819
814
|
self.sim[b[0]].t(b[1])
|
|
820
815
|
return
|
|
821
816
|
|
|
822
|
-
qb, lhv =
|
|
817
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
823
818
|
|
|
824
819
|
for q in qb:
|
|
825
820
|
b = hq[q]
|
|
@@ -835,7 +830,7 @@ class QrackAceBackend:
|
|
|
835
830
|
self.sim[b[0]].adjt(b[1])
|
|
836
831
|
return
|
|
837
832
|
|
|
838
|
-
qb, lhv =
|
|
833
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
839
834
|
|
|
840
835
|
for q in qb:
|
|
841
836
|
b = hq[q]
|
|
@@ -857,9 +852,7 @@ class QrackAceBackend:
|
|
|
857
852
|
gate = self.sim[sim_id].macz if anti else self.sim[sim_id].mcz
|
|
858
853
|
shadow = self._anti_cz_shadow if anti else self._cz_shadow
|
|
859
854
|
else:
|
|
860
|
-
raise RuntimeError(
|
|
861
|
-
"QrackAceBackend._get_gate() should never return identity!"
|
|
862
|
-
)
|
|
855
|
+
raise RuntimeError("QrackAceBackend._get_gate() should never return identity!")
|
|
863
856
|
|
|
864
857
|
return gate, shadow
|
|
865
858
|
|
|
@@ -896,11 +889,7 @@ class QrackAceBackend:
|
|
|
896
889
|
b2 = hq2[q2]
|
|
897
890
|
if b1[0] == b2[0]:
|
|
898
891
|
gate_fn([b1[1]], b2[1])
|
|
899
|
-
elif (
|
|
900
|
-
lq1_lr
|
|
901
|
-
or (b1[1] == b2[1])
|
|
902
|
-
or ((len(qb1) == 2) and (b1[1] == (b2[1] & 1)))
|
|
903
|
-
):
|
|
892
|
+
elif lq1_lr or (b1[1] == b2[1]) or ((len(qb1) == 2) and (b1[1] == (b2[1] & 1))):
|
|
904
893
|
shadow_fn(b1, b2)
|
|
905
894
|
|
|
906
895
|
def _cpauli(self, lq1, lq2, anti, pauli):
|
|
@@ -917,8 +906,8 @@ class QrackAceBackend:
|
|
|
917
906
|
|
|
918
907
|
self._correct(lq1)
|
|
919
908
|
|
|
920
|
-
qb1, lhv1 =
|
|
921
|
-
qb2, lhv2 =
|
|
909
|
+
qb1, lhv1 = QrackAceBackend._get_qb_lhv_indices(hq1)
|
|
910
|
+
qb2, lhv2 = QrackAceBackend._get_qb_lhv_indices(hq2)
|
|
922
911
|
# Apply cross coupling on hardware qubits first
|
|
923
912
|
self._apply_coupling(pauli, anti, qb1, lhv1, hq1, qb2, lhv2, hq2, lq1_lr)
|
|
924
913
|
# Apply coupling to the local-hidden-variable target
|
|
@@ -1030,9 +1019,7 @@ class QrackAceBackend:
|
|
|
1030
1019
|
self.sim[hq[4][0]].prob(hq[4][1]),
|
|
1031
1020
|
]
|
|
1032
1021
|
# Balancing suggestion from Elara (the custom OpenAI GPT)
|
|
1033
|
-
prms = math.sqrt(
|
|
1034
|
-
(p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7
|
|
1035
|
-
)
|
|
1022
|
+
prms = math.sqrt((p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7)
|
|
1036
1023
|
qrms = math.sqrt(
|
|
1037
1024
|
(
|
|
1038
1025
|
(1 - p[0]) ** 2
|
|
@@ -1065,7 +1052,7 @@ class QrackAceBackend:
|
|
|
1065
1052
|
p = self.prob(lq)
|
|
1066
1053
|
result = ((p + self._epsilon) >= 1) or (random.random() < p)
|
|
1067
1054
|
|
|
1068
|
-
qb, lhv =
|
|
1055
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
1069
1056
|
|
|
1070
1057
|
for q in qb:
|
|
1071
1058
|
b = hq[q]
|
|
@@ -1091,7 +1078,7 @@ class QrackAceBackend:
|
|
|
1091
1078
|
|
|
1092
1079
|
self._correct(lq)
|
|
1093
1080
|
|
|
1094
|
-
qb, lhv =
|
|
1081
|
+
qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
|
|
1095
1082
|
|
|
1096
1083
|
for q in qb:
|
|
1097
1084
|
b = hq[q]
|
|
@@ -1184,17 +1171,11 @@ class QrackAceBackend:
|
|
|
1184
1171
|
(-1 * float(operation.params[1])) + math.pi / 2,
|
|
1185
1172
|
)
|
|
1186
1173
|
elif name == "rx":
|
|
1187
|
-
self._sim.r(
|
|
1188
|
-
Pauli.PauliX, float(operation.params[0]), operation.qubits[0]._index
|
|
1189
|
-
)
|
|
1174
|
+
self._sim.r(Pauli.PauliX, float(operation.params[0]), operation.qubits[0]._index)
|
|
1190
1175
|
elif name == "ry":
|
|
1191
|
-
self._sim.r(
|
|
1192
|
-
Pauli.PauliY, float(operation.params[0]), operation.qubits[0]._index
|
|
1193
|
-
)
|
|
1176
|
+
self._sim.r(Pauli.PauliY, float(operation.params[0]), operation.qubits[0]._index)
|
|
1194
1177
|
elif name == "rz":
|
|
1195
|
-
self._sim.r(
|
|
1196
|
-
Pauli.PauliZ, float(operation.params[0]), operation.qubits[0]._index
|
|
1197
|
-
)
|
|
1178
|
+
self._sim.r(Pauli.PauliZ, float(operation.params[0]), operation.qubits[0]._index)
|
|
1198
1179
|
elif name == "h":
|
|
1199
1180
|
self._sim.h(operation.qubits[0]._index)
|
|
1200
1181
|
elif name == "x":
|
|
@@ -1259,9 +1240,9 @@ class QrackAceBackend:
|
|
|
1259
1240
|
cregbit = clbit
|
|
1260
1241
|
|
|
1261
1242
|
regbit = 1 << cregbit
|
|
1262
|
-
self._classical_register = (
|
|
1263
|
-
|
|
1264
|
-
)
|
|
1243
|
+
self._classical_register = (self._classical_register & (~regbit)) | (
|
|
1244
|
+
qubit_outcome << cregbit
|
|
1245
|
+
)
|
|
1265
1246
|
|
|
1266
1247
|
elif name == "bfunc":
|
|
1267
1248
|
mask = int(operation.mask, 16)
|
|
@@ -1376,9 +1357,7 @@ class QrackAceBackend:
|
|
|
1376
1357
|
if operation.name == "id" or operation.name == "barrier":
|
|
1377
1358
|
continue
|
|
1378
1359
|
|
|
1379
|
-
if is_initializing and (
|
|
1380
|
-
(operation.name == "measure") or (operation.name == "reset")
|
|
1381
|
-
):
|
|
1360
|
+
if is_initializing and ((operation.name == "measure") or (operation.name == "reset")):
|
|
1382
1361
|
continue
|
|
1383
1362
|
|
|
1384
1363
|
is_initializing = False
|
|
@@ -1436,14 +1415,13 @@ class QrackAceBackend:
|
|
|
1436
1415
|
self._sample_cregbits = []
|
|
1437
1416
|
|
|
1438
1417
|
if self._sample_measure and (len(self._sample_qubits) > 0):
|
|
1439
|
-
_data = self._add_sample_measure(
|
|
1440
|
-
self._sample_qubits, self._sample_clbits, self._shots
|
|
1441
|
-
)
|
|
1418
|
+
_data = self._add_sample_measure(self._sample_qubits, self._sample_clbits, self._shots)
|
|
1442
1419
|
|
|
1443
1420
|
del self._sim
|
|
1444
1421
|
|
|
1445
1422
|
return _data
|
|
1446
1423
|
|
|
1424
|
+
@staticmethod
|
|
1447
1425
|
def get_qiskit_basis_gates():
|
|
1448
1426
|
return [
|
|
1449
1427
|
"id",
|
|
@@ -1528,17 +1506,13 @@ class QrackAceBackend:
|
|
|
1528
1506
|
noise_model.add_quantum_error(depolarizing_error(y, 2), "cx", [a, b])
|
|
1529
1507
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
|
|
1530
1508
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
|
|
1531
|
-
noise_model.add_quantum_error(
|
|
1532
|
-
depolarizing_error(y_swap, 2), "swap", [a, b]
|
|
1533
|
-
)
|
|
1509
|
+
noise_model.add_quantum_error(depolarizing_error(y_swap, 2), "swap", [a, b])
|
|
1534
1510
|
else:
|
|
1535
1511
|
y_cy = 1 - (1 - y) ** 2
|
|
1536
1512
|
y_swap = 1 - (1 - y) ** 3
|
|
1537
1513
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cx", [a, b])
|
|
1538
1514
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
|
|
1539
1515
|
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
|
|
1540
|
-
noise_model.add_quantum_error(
|
|
1541
|
-
depolarizing_error(y_swap, 2), "swap", [a, b]
|
|
1542
|
-
)
|
|
1516
|
+
noise_model.add_quantum_error(depolarizing_error(y_swap, 2), "swap", [a, b])
|
|
1543
1517
|
|
|
1544
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
|
|
pyqrack/qrack_neuron.py
CHANGED
|
@@ -64,7 +64,7 @@ class QrackNeuron:
|
|
|
64
64
|
self.nid = Qrack.qrack_lib.init_qneuron(
|
|
65
65
|
simulator.sid,
|
|
66
66
|
len(controls),
|
|
67
|
-
|
|
67
|
+
QrackNeuron._ulonglong_byref(controls),
|
|
68
68
|
target,
|
|
69
69
|
activation_fn,
|
|
70
70
|
alpha,
|
|
@@ -99,15 +99,32 @@ class QrackNeuron:
|
|
|
99
99
|
self._throw_if_error()
|
|
100
100
|
return result
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
@staticmethod
|
|
103
|
+
def _ulonglong_byref(a):
|
|
103
104
|
return (ctypes.c_ulonglong * len(a))(*a)
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
@staticmethod
|
|
107
|
+
def _real1_byref(a):
|
|
106
108
|
# This needs to be c_double, if PyQrack is built with fp64.
|
|
107
109
|
if Qrack.fppow < 6:
|
|
108
110
|
return (ctypes.c_float * len(a))(*a)
|
|
109
111
|
return (ctypes.c_double * len(a))(*a)
|
|
110
112
|
|
|
113
|
+
def set_simulator(self, s):
|
|
114
|
+
"""Set the neuron simulator
|
|
115
|
+
|
|
116
|
+
Set the simulator used by this neuron
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
s(QrackSimulator): The simulator to use
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
RuntimeError: QrackSimulator raised an exception.
|
|
123
|
+
"""
|
|
124
|
+
Qrack.qrack_lib.set_qneuron_sim(self.nid, s.sid)
|
|
125
|
+
self._throw_if_error()
|
|
126
|
+
self.simulator = s
|
|
127
|
+
|
|
111
128
|
def set_angles(self, a):
|
|
112
129
|
"""Directly sets the neuron parameters.
|
|
113
130
|
|
|
@@ -125,7 +142,7 @@ class QrackNeuron:
|
|
|
125
142
|
raise ValueError(
|
|
126
143
|
"Angles 'a' in QrackNeuron.set_angles() must contain at least (2 ** len(self.controls)) elements."
|
|
127
144
|
)
|
|
128
|
-
Qrack.qrack_lib.set_qneuron_angles(self.nid,
|
|
145
|
+
Qrack.qrack_lib.set_qneuron_angles(self.nid, QrackNeuron._real1_byref(a))
|
|
129
146
|
self._throw_if_error()
|
|
130
147
|
|
|
131
148
|
def get_angles(self):
|
|
@@ -137,7 +154,7 @@ class QrackNeuron:
|
|
|
137
154
|
Raises:
|
|
138
155
|
RuntimeError: QrackNeuron C++ library raised an exception.
|
|
139
156
|
"""
|
|
140
|
-
ket =
|
|
157
|
+
ket = QrackNeuron._real1_byref([0.0] * (1 << len(self.controls)))
|
|
141
158
|
Qrack.qrack_lib.get_qneuron_angles(self.nid, ket)
|
|
142
159
|
self._throw_if_error()
|
|
143
160
|
return list(ket)
|
|
@@ -261,8 +278,9 @@ class QrackNeuron:
|
|
|
261
278
|
Qrack.qrack_lib.qneuron_learn_permutation(self.nid, eta, e, r)
|
|
262
279
|
self._throw_if_error()
|
|
263
280
|
|
|
281
|
+
@staticmethod
|
|
264
282
|
def quantile_bounds(vec, bits):
|
|
265
|
-
"""
|
|
283
|
+
"""Calculate vector quantile bounds
|
|
266
284
|
|
|
267
285
|
This is a static helper method to calculate the quantile
|
|
268
286
|
bounds of 2 ** bits worth of quantiles.
|
|
@@ -280,10 +298,15 @@ class QrackNeuron:
|
|
|
280
298
|
n = len(vec)
|
|
281
299
|
vec_sorted = sorted(vec)
|
|
282
300
|
|
|
283
|
-
return
|
|
301
|
+
return (
|
|
302
|
+
[vec_sorted[0]]
|
|
303
|
+
+ [vec_sorted[(k * n) // bins] for k in range(1, bins)]
|
|
304
|
+
+ [vec_sorted[-1]]
|
|
305
|
+
)
|
|
284
306
|
|
|
307
|
+
@staticmethod
|
|
285
308
|
def discretize(vec, bounds):
|
|
286
|
-
"""
|
|
309
|
+
"""Discretize vector by quantile bounds
|
|
287
310
|
|
|
288
311
|
This is a static helper method to discretize a numerical
|
|
289
312
|
vector according to quantile bounds calculated by the
|
|
@@ -311,8 +334,9 @@ class QrackNeuron:
|
|
|
311
334
|
|
|
312
335
|
return vec_discrete
|
|
313
336
|
|
|
337
|
+
@staticmethod
|
|
314
338
|
def flatten_and_transpose(arr):
|
|
315
|
-
"""
|
|
339
|
+
"""Flatten and transpose feature matrix
|
|
316
340
|
|
|
317
341
|
This is a static helper method to convert a multi-feature
|
|
318
342
|
bit-row matrix to an observation-row matrix with flat
|
|
@@ -326,8 +350,9 @@ class QrackNeuron:
|
|
|
326
350
|
"""
|
|
327
351
|
return list(zip(*[item for sublist in arr for item in sublist]))
|
|
328
352
|
|
|
353
|
+
@staticmethod
|
|
329
354
|
def bin_endpoints_average(bounds):
|
|
330
|
-
"""
|
|
355
|
+
"""Bin endpoints average
|
|
331
356
|
|
|
332
357
|
This is a static helper method that accepts the output
|
|
333
358
|
bins from quantile_bounds() and returns the average points
|