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.
Files changed (26) hide show
  1. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/Makefile +1 -1
  2. {pyqrack_cuda-1.34.4/pyqrack_cuda.egg-info → pyqrack_cuda-1.34.6}/PKG-INFO +1 -1
  3. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_circuit.py +81 -96
  4. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6/pyqrack_cuda.egg-info}/PKG-INFO +1 -1
  5. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/SOURCES.txt +0 -1
  6. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/setup.py +1 -1
  7. pyqrack_cuda-1.34.4/pyqrack/qrack_system/qrack_lib/libqrack_pinvoke.so +0 -0
  8. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/LICENSE +0 -0
  9. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/MANIFEST.in +0 -0
  10. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/README.md +0 -0
  11. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyproject.toml +0 -0
  12. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/__init__.py +0 -0
  13. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/neuron_activation_fn.py +0 -0
  14. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/pauli.py +0 -0
  15. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_neuron.py +0 -0
  16. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_simulator.py +0 -0
  17. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_system/__init__.py +0 -0
  18. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/qrack_system/qrack_system.py +0 -0
  19. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/quimb_circuit_type.py +0 -0
  20. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/util/__init__.py +0 -0
  21. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack/util/convert_qiskit_circuit_to_qasm_experiment.py +0 -0
  22. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/dependency_links.txt +0 -0
  23. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/not-zip-safe +0 -0
  24. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/requires.txt +0 -0
  25. {pyqrack_cuda-1.34.4 → pyqrack_cuda-1.34.6}/pyqrack_cuda.egg-info/top_level.txt +0 -0
  26. {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 d102dd0b166452c47027698eb25ef1430ff50bed; cd ..
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyqrack-cuda
3
- Version: 1.34.4
3
+ Version: 1.34.6
4
4
  Summary: pyqrack - Pure Python vm6502q/qrack Wrapper
5
5
  Home-page: https://github.com/vm6502q/pyqrack
6
6
  Author: Daniel Strano
@@ -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 U3Gate, UCGate
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 = i + 1
337
+ i += 1
306
338
  circ = QuantumCircuit(num_qubits)
307
339
 
308
340
  num_gates = int(tokens[i])
309
- i = i + 1
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 = i + 1
346
+ i += 1
314
347
 
315
348
  control_count = int(tokens[i])
316
- i = i + 1
349
+ i += 1
317
350
  controls = []
318
351
  for j in range(control_count):
319
352
  controls.append(int(tokens[i]))
320
- i = i + 1
353
+ i += 1
321
354
 
322
355
  payload_count = int(tokens[i])
323
- i = i + 1
356
+ i += 1
324
357
  payloads = {}
325
358
  for j in range(payload_count):
326
359
  key = int(tokens[i])
327
- i = i + 1
328
- op = np.zeros((2,2), dtype=complex)
329
- row = []
330
- for _ in range(2):
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
- row.append(float(amp[0]) + float(amp[1])*1j)
347
- i = i + 1
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
- return circ
368
+ mtrx = QrackCircuit._make_mtrx_unitary(mtrx)
387
369
 
388
- def _u3_to_mtrx(params):
389
- th = float(params[0])
390
- ph = float(params[1])
391
- lm = float(params[2])
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
- c = math.cos(th / 2)
394
- s = math.sin(th / 2)
395
- el = np.exp(1j * lm)
396
- ep = np.exp(1j * ph)
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 [ c + 0j, -el * s, ep * s, el * ep * c]
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
- ctrls = []
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyqrack-cuda
3
- Version: 1.34.4
3
+ Version: 1.34.6
4
4
  Summary: pyqrack - Pure Python vm6502q/qrack Wrapper
5
5
  Home-page: https://github.com/vm6502q/pyqrack
6
6
  Author: Daniel Strano
@@ -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
@@ -7,7 +7,7 @@ from setuptools import setup
7
7
  from setuptools.command.build_py import build_py
8
8
 
9
9
 
10
- VERSION = "1.34.4"
10
+ VERSION = "1.34.6"
11
11
 
12
12
  # Read long description from README.
13
13
  README_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'README.md')
File without changes
File without changes
File without changes
File without changes