pyqrack-cuda 1.58.0__tar.gz → 1.58.6__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.58.0/pyqrack_cuda.egg-info → pyqrack_cuda-1.58.6}/PKG-INFO +1 -1
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/qrack_ace_backend.py +137 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/qrack_system/qrack_system.py +5 -1
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6/pyqrack_cuda.egg-info}/PKG-INFO +1 -1
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/setup.py +1 -1
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/LICENSE +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/MANIFEST.in +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/Makefile +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/README.md +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyproject.toml +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/__init__.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/pauli.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack_cuda.egg-info/SOURCES.txt +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack_cuda.egg-info/dependency_links.txt +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack_cuda.egg-info/not-zip-safe +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack_cuda.egg-info/requires.txt +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/pyqrack_cuda.egg-info/top_level.txt +0 -0
- {pyqrack_cuda-1.58.0 → pyqrack_cuda-1.58.6}/setup.cfg +0 -0
@@ -102,6 +102,45 @@ class LHVQubit:
|
|
102
102
|
self.ry(theta)
|
103
103
|
self.rz(phi)
|
104
104
|
|
105
|
+
# Provided verbatim by Elara (the custom OpenAI GPT):
|
106
|
+
def mtrx(self, matrix):
|
107
|
+
"""
|
108
|
+
Apply a 2x2 unitary matrix to the LHV Bloch vector using only standard math/cmath.
|
109
|
+
Matrix format: [a, b, c, d] for [[a, b], [c, d]]
|
110
|
+
"""
|
111
|
+
a, b, c, d = matrix
|
112
|
+
|
113
|
+
# Current Bloch vector
|
114
|
+
x, y, z = self.bloch
|
115
|
+
|
116
|
+
# Convert to density matrix ρ = ½ (I + xσx + yσy + zσz)
|
117
|
+
rho = [[(1 + z) / 2, (x - 1j * y) / 2], [(x + 1j * y) / 2, (1 - z) / 2]]
|
118
|
+
|
119
|
+
# Compute U * ρ
|
120
|
+
u_rho = [
|
121
|
+
[a * rho[0][0] + b * rho[1][0], a * rho[0][1] + b * rho[1][1]],
|
122
|
+
[c * rho[0][0] + d * rho[1][0], c * rho[0][1] + d * rho[1][1]],
|
123
|
+
]
|
124
|
+
|
125
|
+
# Compute (U * ρ) * U†
|
126
|
+
rho_prime = [
|
127
|
+
[
|
128
|
+
u_rho[0][0] * a.conjugate() + u_rho[0][1] * b.conjugate(),
|
129
|
+
u_rho[0][0] * c.conjugate() + u_rho[0][1] * d.conjugate(),
|
130
|
+
],
|
131
|
+
[
|
132
|
+
u_rho[1][0] * a.conjugate() + u_rho[1][1] * b.conjugate(),
|
133
|
+
u_rho[1][0] * c.conjugate() + u_rho[1][1] * d.conjugate(),
|
134
|
+
],
|
135
|
+
]
|
136
|
+
|
137
|
+
# Extract Bloch components: Tr(ρ'σi) = 2 * Re[...]
|
138
|
+
new_x = 2 * rho_prime[0][1].real + 2 * rho_prime[1][0].real
|
139
|
+
new_y = 2 * (rho_prime[0][1].imag - rho_prime[1][0].imag)
|
140
|
+
new_z = 2 * rho_prime[0][0].real - 1 # since Tr(ρ') = 1
|
141
|
+
|
142
|
+
self.bloch = [new_x, new_y, new_z]
|
143
|
+
|
105
144
|
def prob(self, basis=Pauli.PauliZ):
|
106
145
|
"""Sample a classical outcome from the current 'quantum' state"""
|
107
146
|
if basis == Pauli.PauliZ:
|
@@ -404,6 +443,56 @@ class QrackAceBackend:
|
|
404
443
|
|
405
444
|
return qb, lhv
|
406
445
|
|
446
|
+
def get_bloch_angles(self, hq):
|
447
|
+
sim = self.sim[hq[0]]
|
448
|
+
q = hq[1]
|
449
|
+
|
450
|
+
# Z axis
|
451
|
+
z = 1 - 2 * sim.prob(q)
|
452
|
+
prob = z**2
|
453
|
+
|
454
|
+
# X axis
|
455
|
+
sim.h(q)
|
456
|
+
x = 1 - 2 * sim.prob(q)
|
457
|
+
prob += x**2
|
458
|
+
sim.h(q)
|
459
|
+
|
460
|
+
# Y axis
|
461
|
+
sim.adjs(q)
|
462
|
+
sim.h(q)
|
463
|
+
y = 1 - 2 * sim.prob(q)
|
464
|
+
prob += y**2
|
465
|
+
sim.h(q)
|
466
|
+
sim.s(q)
|
467
|
+
|
468
|
+
prob = math.sqrt(prob)
|
469
|
+
inclination = math.atan2(math.sqrt(x**2 + y**2), z)
|
470
|
+
azimuth = math.atan2(y, x)
|
471
|
+
|
472
|
+
return prob, azimuth, inclination
|
473
|
+
|
474
|
+
def rotate_to_bloch(
|
475
|
+
self, hq, azimuth_curr, inclination_curr, azimuth_target, inclination_target
|
476
|
+
):
|
477
|
+
sim = self.sim[hq[0]]
|
478
|
+
q = hq[1]
|
479
|
+
|
480
|
+
delta_azimuth = azimuth_target - azimuth_curr
|
481
|
+
delta_inclination = inclination_target - inclination_curr
|
482
|
+
|
483
|
+
# Apply rotation as "Azimuth, Inclination" (AI)
|
484
|
+
cosA = math.cos(delta_azimuth)
|
485
|
+
sinA = math.sin(delta_azimuth)
|
486
|
+
cosI = math.cos(delta_inclination / 2)
|
487
|
+
sinI = math.sin(delta_inclination / 2)
|
488
|
+
|
489
|
+
m00 = complex(cosI, 0)
|
490
|
+
m01 = complex(-cosA, sinA) * sinI
|
491
|
+
m10 = complex(cosA, sinA) * sinI
|
492
|
+
m11 = complex(cosI, 0)
|
493
|
+
|
494
|
+
sim.mtrx([m00, m01, m10, m11], q)
|
495
|
+
|
407
496
|
def _correct(self, lq, phase=False):
|
408
497
|
hq = self._unpack(lq)
|
409
498
|
|
@@ -454,6 +543,31 @@ class QrackAceBackend:
|
|
454
543
|
hq[q].x()
|
455
544
|
else:
|
456
545
|
self.sim[hq[q][0]].x(hq[q][1])
|
546
|
+
|
547
|
+
p, a, i = [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]
|
548
|
+
p[0], a[0], i[0] = self.get_bloch_angles(hq[0])
|
549
|
+
p[1], a[1], i[1] = self.get_bloch_angles(hq[1])
|
550
|
+
p[3], a[3], i[3] = self.get_bloch_angles(hq[3])
|
551
|
+
p[4], a[4], i[4] = self.get_bloch_angles(hq[4])
|
552
|
+
|
553
|
+
indices = []
|
554
|
+
a_target = 0
|
555
|
+
i_target = 0
|
556
|
+
weight = 0
|
557
|
+
for x in range(5):
|
558
|
+
if p[x] <= 0.5:
|
559
|
+
continue
|
560
|
+
indices.append(x)
|
561
|
+
w = (0.5 - p[x])
|
562
|
+
a_target += w * a[x]
|
563
|
+
i_target += w * i[x]
|
564
|
+
weight += w
|
565
|
+
|
566
|
+
if len(indices) > 1:
|
567
|
+
a_target /= weight
|
568
|
+
i_target /= weight
|
569
|
+
for x in indices:
|
570
|
+
self.rotate_to_bloch(hq[x], a[x], i[x], a_target, i_target)
|
457
571
|
else:
|
458
572
|
# RMS
|
459
573
|
p = [
|
@@ -473,6 +587,29 @@ class QrackAceBackend:
|
|
473
587
|
else:
|
474
588
|
self.sim[hq[q][0]].x(hq[q][1])
|
475
589
|
|
590
|
+
p, a, i = [0, 0], [0, 0], [0, 0]
|
591
|
+
p[0], a[0], i[0] = self.get_bloch_angles(hq[0])
|
592
|
+
p[1], a[1], i[1] = self.get_bloch_angles(hq[1])
|
593
|
+
|
594
|
+
indices = []
|
595
|
+
a_target = 0
|
596
|
+
i_target = 0
|
597
|
+
weight = 0
|
598
|
+
for x in range(2):
|
599
|
+
if p[x] <= 0.5:
|
600
|
+
continue
|
601
|
+
indices.append(x)
|
602
|
+
w = (0.5 - p[x])
|
603
|
+
a_target += x * a[x]
|
604
|
+
i_target += w * i[x]
|
605
|
+
weight += w
|
606
|
+
|
607
|
+
if len(indices) > 1:
|
608
|
+
a_target /= weight
|
609
|
+
i_target /= weight
|
610
|
+
for x in indices:
|
611
|
+
self.rotate_to_bloch(hq[x], a[x], i[x], a_target, i_target)
|
612
|
+
|
476
613
|
if phase:
|
477
614
|
for q in qb:
|
478
615
|
b = hq[q]
|
@@ -147,7 +147,11 @@ class QrackSystem:
|
|
147
147
|
self.qrack_lib.set_device.argtypes = [c_ulonglong, c_longlong]
|
148
148
|
|
149
149
|
self.qrack_lib.set_device_list.restype = None
|
150
|
-
self.qrack_lib.set_device_list.argtypes = [
|
150
|
+
self.qrack_lib.set_device_list.argtypes = [
|
151
|
+
c_ulonglong,
|
152
|
+
c_ulonglong,
|
153
|
+
POINTER(c_longlong),
|
154
|
+
]
|
151
155
|
|
152
156
|
# pseudo-quantum
|
153
157
|
|
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
|