pyqrack-cuda 1.34.4__tar.gz → 1.34.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.34.4 → pyqrack_cuda-1.34.6}/Makefile +1 -1
- {pyqrack_cuda-1.34.4/pyqrack_cuda.egg-info → pyqrack_cuda-1.34.6}/PKG-INFO +1 -1
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_circuit.py +81 -96
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6/pyqrack_cuda.egg-info}/PKG-INFO +1 -1
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/SOURCES.txt +0 -1
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/setup.py +1 -1
- pyqrack_cuda-1.34.4/pyqrack/qrack_system/qrack_lib/libqrack_pinvoke.so +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/LICENSE +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/MANIFEST.in +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/README.md +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyproject.toml +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/__init__.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/pauli.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/util/__init__.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/util/convert_qiskit_circuit_to_qasm_experiment.py +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/dependency_links.txt +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/not-zip-safe +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/requires.txt +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/top_level.txt +0 -0
- {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/setup.cfg +0 -0
@@ -18,7 +18,7 @@ help:
|
|
18
18
|
build-deps:
|
19
19
|
ifneq ($(OS),Windows_NT)
|
20
20
|
ifeq ($(QRACK_PRESENT),)
|
21
|
-
git clone https://github.com/unitaryfund/qrack.git; cd qrack; git checkout
|
21
|
+
git clone https://github.com/unitaryfund/qrack.git; cd qrack; git checkout 3d2bdc25d5a676ce48691e46eef57737b8acdd04; cd ..
|
22
22
|
endif
|
23
23
|
mkdir -p qrack/build
|
24
24
|
ifeq ($(UNAME_S),Linux)
|
@@ -12,9 +12,10 @@ _IS_QISKIT_AVAILABLE = True
|
|
12
12
|
try:
|
13
13
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
14
14
|
from qiskit.compiler.transpiler import transpile
|
15
|
-
from qiskit.circuit.library import
|
15
|
+
from qiskit.circuit.library import UCGate
|
16
16
|
import numpy as np
|
17
17
|
import math
|
18
|
+
import sys
|
18
19
|
except ImportError:
|
19
20
|
_IS_QISKIT_AVAILABLE = False
|
20
21
|
|
@@ -32,22 +33,6 @@ except ImportError:
|
|
32
33
|
_IS_TENSORCIRCUIT_AVAILABLE = False
|
33
34
|
|
34
35
|
|
35
|
-
def euler_angles_1q(m):
|
36
|
-
phase = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) ** (-1.0/2.0)
|
37
|
-
U = [[phase * m[0][0], phase * m[0][1]], [phase * m[1][0], phase * m[1][1]]]
|
38
|
-
|
39
|
-
theta = 2 * math.atan2(abs(U[1][0]), abs(U[0][0]))
|
40
|
-
|
41
|
-
# Find phi and lambda
|
42
|
-
phiplambda = 2 * np.angle(U[1][1])
|
43
|
-
phimlambda = 2 * np.angle(U[1][0])
|
44
|
-
|
45
|
-
phi = (phiplambda + phimlambda) / 2.0
|
46
|
-
lamb = (phiplambda - phimlambda) / 2.0
|
47
|
-
|
48
|
-
return theta, phi, lamb
|
49
|
-
|
50
|
-
|
51
36
|
class QrackCircuit:
|
52
37
|
"""Class that exposes the QCircuit class of Qrack
|
53
38
|
|
@@ -85,6 +70,53 @@ class QrackCircuit:
|
|
85
70
|
t = [(c.real, c.imag) for c in a]
|
86
71
|
return self._double_byref([float(item) for sublist in t for item in sublist])
|
87
72
|
|
73
|
+
def _mtrx_to_u4(m):
|
74
|
+
nrm = abs(m[0])
|
75
|
+
if (nrm * nrm) < sys.float_info.epsilon:
|
76
|
+
phase = 1.0 + 0.0j
|
77
|
+
th = math.pi;
|
78
|
+
else:
|
79
|
+
phase = m[0] / nrm
|
80
|
+
if nrm > 1.0:
|
81
|
+
nrm = 1.0
|
82
|
+
th = 2 * math.acos(nrm)
|
83
|
+
|
84
|
+
nrm1 = abs(m[1])
|
85
|
+
nrm2 = abs(m[2])
|
86
|
+
nrm1 *= nrm1
|
87
|
+
nrm2 *= nrm2
|
88
|
+
if (nrm1 < sys.float_info.epsilon) or (nrm2 < sys.float_info.epsilon):
|
89
|
+
ph = np.angle(m[3] / phase)
|
90
|
+
lm = 0.0
|
91
|
+
else:
|
92
|
+
ph = np.angle(m[2] / phase)
|
93
|
+
lm = np.angle(-m[1] / phase)
|
94
|
+
|
95
|
+
return th, ph, lm, np.angle(phase)
|
96
|
+
|
97
|
+
def _u3_to_mtrx(params):
|
98
|
+
th = float(params[0])
|
99
|
+
ph = float(params[1])
|
100
|
+
lm = float(params[2])
|
101
|
+
|
102
|
+
c = math.cos(th / 2)
|
103
|
+
s = math.sin(th / 2)
|
104
|
+
el = np.exp(1j * lm)
|
105
|
+
ep = np.exp(1j * ph)
|
106
|
+
|
107
|
+
return [c + 0j, -el * s, ep * s, ep * el * c]
|
108
|
+
|
109
|
+
def _u4_to_mtrx(params):
|
110
|
+
m = QrackCircuit._u3_to_mtrx(params)
|
111
|
+
g = np.exp(1j * float(params[3]))
|
112
|
+
for i in range(4):
|
113
|
+
m[i] *= g
|
114
|
+
|
115
|
+
return m
|
116
|
+
|
117
|
+
def _make_mtrx_unitary(m):
|
118
|
+
return QrackCircuit._u4_to_mtrx(QrackCircuit._mtrx_to_u4(m))
|
119
|
+
|
88
120
|
def clone(self):
|
89
121
|
"""Make a new circuit that is an exact clone of this circuit
|
90
122
|
|
@@ -302,100 +334,56 @@ class QrackCircuit:
|
|
302
334
|
|
303
335
|
i = 0
|
304
336
|
num_qubits = int(tokens[i])
|
305
|
-
i
|
337
|
+
i += 1
|
306
338
|
circ = QuantumCircuit(num_qubits)
|
307
339
|
|
308
340
|
num_gates = int(tokens[i])
|
309
|
-
i
|
341
|
+
i += 1
|
310
342
|
|
343
|
+
identity = np.eye(2, dtype=complex)
|
311
344
|
for g in range(num_gates):
|
312
345
|
target = int(tokens[i])
|
313
|
-
i
|
346
|
+
i += 1
|
314
347
|
|
315
348
|
control_count = int(tokens[i])
|
316
|
-
i
|
349
|
+
i += 1
|
317
350
|
controls = []
|
318
351
|
for j in range(control_count):
|
319
352
|
controls.append(int(tokens[i]))
|
320
|
-
i
|
353
|
+
i += 1
|
321
354
|
|
322
355
|
payload_count = int(tokens[i])
|
323
|
-
i
|
356
|
+
i += 1
|
324
357
|
payloads = {}
|
325
358
|
for j in range(payload_count):
|
326
359
|
key = int(tokens[i])
|
327
|
-
i
|
328
|
-
|
329
|
-
|
330
|
-
for _ in range(
|
331
|
-
amp = tokens[i].replace("(","").replace(")","").split(',')
|
332
|
-
row.append(float(amp[0]) + float(amp[1])*1j)
|
333
|
-
i = i + 1
|
334
|
-
l = math.sqrt(np.real(row[0] * np.conj(row[0]) + row[1] * np.conj(row[1])))
|
335
|
-
op[0][0] = row[0] / l
|
336
|
-
op[0][1] = row[1] / l
|
337
|
-
|
338
|
-
if np.abs(op[0][0] - row[0]) > 1e-5:
|
339
|
-
print("Warning: gate ", str(g), ", payload ", str(j), " might not be unitary!")
|
340
|
-
if np.abs(op[0][1] - row[1]) > 1e-5:
|
341
|
-
print("Warning: gate ", str(g), ", payload ", str(j), " might not be unitary!")
|
342
|
-
|
343
|
-
row = []
|
344
|
-
for _ in range(2):
|
360
|
+
i += 1
|
361
|
+
|
362
|
+
mtrx = []
|
363
|
+
for _ in range(4):
|
345
364
|
amp = tokens[i].replace("(","").replace(")","").split(',')
|
346
|
-
|
347
|
-
i
|
348
|
-
l = math.sqrt(np.real(row[0] * np.conj(row[0]) + row[1] * np.conj(row[1])))
|
349
|
-
op[1][0] = row[0] / l
|
350
|
-
op[1][1] = row[1] / l
|
351
|
-
|
352
|
-
ph = np.real(np.log(np.linalg.det(op)) / 1j)
|
353
|
-
|
354
|
-
op[1][0] = -np.exp(1j * ph) * np.conj(op[0][1])
|
355
|
-
op[1][1] = np.exp(1j * ph) * np.conj(op[0][0])
|
356
|
-
|
357
|
-
if np.abs(op[1][0] - row[0]) > 1e-5:
|
358
|
-
print("Warning: gate ", str(g), ", payload ", str(j), " might not be unitary!")
|
359
|
-
if np.abs(op[1][1] - row[1]) > 1e-5:
|
360
|
-
print("Warning: gate ", str(g), ", payload ", str(j), " might not be unitary!")
|
361
|
-
|
362
|
-
# Qiskit has a lower tolerance for deviation from numerically unitary.
|
363
|
-
payloads[key] = np.array(op)
|
364
|
-
|
365
|
-
gate_list = []
|
366
|
-
control_pow = 1 << control_count
|
367
|
-
pLen = len(payloads)
|
368
|
-
if (pLen == 1) or ((control_pow - pLen) > (1 << 15)):
|
369
|
-
for c, p in payloads.items():
|
370
|
-
theta, phi, lam = euler_angles_1q(p)
|
371
|
-
if control_count > 0:
|
372
|
-
circ.append(
|
373
|
-
U3Gate(theta, phi, lam).control(num_ctrl_qubits=control_count, ctrl_state=c),
|
374
|
-
controls + [target]
|
375
|
-
)
|
376
|
-
else:
|
377
|
-
circ.append(U3Gate(theta, phi, lam), [target])
|
378
|
-
else:
|
379
|
-
for j in range(control_pow):
|
380
|
-
if j in payloads:
|
381
|
-
gate_list.append(payloads[j])
|
382
|
-
else:
|
383
|
-
gate_list.append(np.array([[1, 0],[0, 1]]))
|
384
|
-
circ.append(UCGate(gate_list), controls + [target])
|
365
|
+
mtrx.append(float(amp[0]) + float(amp[1])*1j)
|
366
|
+
i += 1
|
385
367
|
|
386
|
-
|
368
|
+
mtrx = QrackCircuit._make_mtrx_unitary(mtrx)
|
387
369
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
370
|
+
op = np.eye(2, dtype=complex)
|
371
|
+
op[0][0] = mtrx[0]
|
372
|
+
op[0][1] = mtrx[1]
|
373
|
+
op[1][0] = mtrx[2]
|
374
|
+
op[1][1] = mtrx[3]
|
392
375
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
376
|
+
payloads[key] = op
|
377
|
+
|
378
|
+
gate_list=[]
|
379
|
+
for j in range(1 << control_count):
|
380
|
+
if j in payloads:
|
381
|
+
gate_list.append(payloads[j])
|
382
|
+
else:
|
383
|
+
gate_list.append(identity)
|
384
|
+
circ.append(UCGate(gate_list), [target] + controls)
|
397
385
|
|
398
|
-
return
|
386
|
+
return circ
|
399
387
|
|
400
388
|
def in_from_qiskit_circuit(circ):
|
401
389
|
"""Read a Qiskit circuit into a QrackCircuit
|
@@ -415,11 +403,11 @@ class QrackCircuit:
|
|
415
403
|
)
|
416
404
|
|
417
405
|
out = QrackCircuit()
|
418
|
-
|
419
406
|
basis_gates = ["x", "y", "z", "u", "cx", "cy", "cz", "cu"]
|
420
407
|
circ = transpile(circ, basis_gates=basis_gates, optimization_level=0)
|
421
408
|
for gate in circ.data:
|
422
409
|
o = gate.operation
|
410
|
+
|
423
411
|
op = []
|
424
412
|
if o.name in ["x", "cx"]:
|
425
413
|
op = [0, 1, 1, 0]
|
@@ -429,14 +417,11 @@ class QrackCircuit:
|
|
429
417
|
op = [1, 0, 0, -1]
|
430
418
|
else:
|
431
419
|
op = QrackCircuit._u3_to_mtrx(o.params)
|
420
|
+
|
432
421
|
if o.name in ["x", "y", "z", "u"]:
|
433
422
|
out.mtrx(op, circ.find_bit(gate.qubits[0])[0])
|
434
423
|
else:
|
435
|
-
|
436
|
-
for c in gate.qubits[0:1]:
|
437
|
-
ctrls.append(circ.find_bit(c)[0])
|
438
|
-
|
439
|
-
out.ucmtrx(ctrls, [0, 1, 1, 0], circ.find_bit(gate.qubits[1])[0], 1)
|
424
|
+
out.ucmtrx([circ.find_bit(gate.qubits[0])[0]], op, circ.find_bit(gate.qubits[1])[0], 1)
|
440
425
|
|
441
426
|
return out
|
442
427
|
|
@@ -13,7 +13,6 @@ pyqrack/qrack_simulator.py
|
|
13
13
|
pyqrack/quimb_circuit_type.py
|
14
14
|
pyqrack/qrack_system/__init__.py
|
15
15
|
pyqrack/qrack_system/qrack_system.py
|
16
|
-
pyqrack/qrack_system/qrack_lib/libqrack_pinvoke.so
|
17
16
|
pyqrack/util/__init__.py
|
18
17
|
pyqrack/util/convert_qiskit_circuit_to_qasm_experiment.py
|
19
18
|
pyqrack_cuda.egg-info/PKG-INFO
|
Binary file
|
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
|