pennylane-qrack 0.10.0__tar.gz → 0.10.2__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.

Potentially problematic release.


This version of pennylane-qrack might be problematic. Click here for more details.

Files changed (29) hide show
  1. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/Makefile +1 -1
  2. {pennylane_qrack-0.10.0/pennylane_qrack.egg-info → pennylane_qrack-0.10.2}/PKG-INFO +1 -1
  3. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/catalyst/runtime/include/QuantumDevice.hpp +43 -0
  4. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/catalyst/runtime/include/RuntimeCAPI.h +4 -1
  5. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/catalyst/runtime/include/Types.h +9 -0
  6. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack/_version.py +1 -1
  7. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack/qrack_device.py +51 -25
  8. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2/pennylane_qrack.egg-info}/PKG-INFO +1 -1
  9. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/setup.py +5 -10
  10. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/tests/test_apply.py +13 -17
  11. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/tests/test_integration.py +1 -0
  12. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/CHANGELOG.md +0 -0
  13. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/CMakeLists.txt +0 -0
  14. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/LICENSE +0 -0
  15. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/MANIFEST.in +0 -0
  16. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/README.rst +0 -0
  17. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/catalyst/runtime/include/DataView.hpp +0 -0
  18. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/catalyst/runtime/include/Exception.hpp +0 -0
  19. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack/QrackDeviceConfig.toml +0 -0
  20. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack/__init__.py +0 -0
  21. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack/qrack_device.cpp +0 -0
  22. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack.egg-info/SOURCES.txt +0 -0
  23. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack.egg-info/dependency_links.txt +0 -0
  24. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack.egg-info/entry_points.txt +0 -0
  25. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack.egg-info/requires.txt +0 -0
  26. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/pennylane_qrack.egg-info/top_level.txt +0 -0
  27. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/requirements.txt +0 -0
  28. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/setup.cfg +0 -0
  29. {pennylane_qrack-0.10.0 → pennylane_qrack-0.10.2}/tests/test_units.py +0 -0
@@ -24,7 +24,7 @@ help:
24
24
  build-deps:
25
25
  ifneq ($(OS),Windows_NT)
26
26
  ifeq ($(QRACK_PRESENT),)
27
- git clone https://github.com/unitaryfund/qrack.git; cd qrack; git checkout 61a9f1e4694eab612b5032e884e6f1696842e47d; cd ..
27
+ git clone https://github.com/unitaryfund/qrack.git; cd qrack; git checkout 0dd1e6ce371b69e21bfa33003bc678b3d42713d5; cd ..
28
28
  endif
29
29
  mkdir -p qrack/build
30
30
  ifeq ($(UNAME_S),Linux)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pennylane-qrack
3
- Version: 0.10.0
3
+ Version: 0.10.2
4
4
  Summary: PennyLane plugin for Qrack.
5
5
  Home-page: http://github.com/vm6502q
6
6
  Maintainer: vm6502q
@@ -17,6 +17,7 @@
17
17
  #include <complex>
18
18
  #include <memory>
19
19
  #include <optional>
20
+ #include <random>
20
21
  #include <vector>
21
22
 
22
23
  #include "DataView.hpp"
@@ -103,6 +104,26 @@ struct QuantumDevice {
103
104
  */
104
105
  [[nodiscard]] virtual auto GetDeviceShots() const -> size_t = 0;
105
106
 
107
+ /**
108
+ * @brief Set the PRNG of the device.
109
+ *
110
+ * The Catalyst runtime enables seeded program execution on non-hardware devices.
111
+ * A random number generator instance is managed by the runtime to predictably
112
+ * generate results for non-deterministic programs, such as those involving `Measure`
113
+ * calls.
114
+ * Devices implementing support for this feature do not need to use the provided
115
+ * PRNG instance as their sole source of random numbers, but it is expected that the
116
+ * the same instance state will predictable and reproducibly generate the same
117
+ * program results. It is also expected that the provided PRNG state is evolved
118
+ * sufficiently so that two device executions sharing the same instance do not produce
119
+ * identical results.
120
+ * The provided PRNG instance is not thread-locked, and devices wishing to share it
121
+ * across threads will need to provide their own thread-safety.
122
+ *
123
+ * @param gen The std::mt19937 PRNG object.
124
+ */
125
+ virtual void SetDevicePRNG([[maybe_unused]] std::mt19937 *gen){};
126
+
106
127
  /**
107
128
  * @brief Start recording a quantum tape if provided.
108
129
  *
@@ -138,6 +159,28 @@ struct QuantumDevice {
138
159
  */
139
160
  virtual void PrintState() = 0;
140
161
 
162
+ /**
163
+ * @brief Prepare subsystems using the given ket vector in the computational basis.
164
+ *
165
+ * @param state A state vector of size 2**len(wires)
166
+ * @param wires The wire(s) the operation acts on
167
+ */
168
+ virtual void SetState(DataView<std::complex<double>, 1> &, std::vector<QubitIdType> &)
169
+ {
170
+ RT_FAIL("Unsupported functionality");
171
+ }
172
+
173
+ /**
174
+ * @brief Prepares a single computational basis state.
175
+ *
176
+ * @param n Prepares the basis state |n>, where n is an array of integers from the set {0, 1}
177
+ * @param wires The wire(s) the operation acts on
178
+ */
179
+ virtual void SetBasisState(DataView<int8_t, 1> &, std::vector<QubitIdType> &)
180
+ {
181
+ RT_FAIL("Unsupported functionality");
182
+ }
183
+
141
184
  /**
142
185
  * @brief Apply a single gate to the state vector of a device with its name if this is
143
186
  * supported.
@@ -24,7 +24,7 @@ extern "C" {
24
24
 
25
25
  // Quantum Runtime Instructions
26
26
  void __catalyst__rt__fail_cstr(const char *);
27
- void __catalyst__rt__initialize();
27
+ void __catalyst__rt__initialize(uint32_t *seed);
28
28
  void __catalyst__rt__device_init(int8_t *, int8_t *, int8_t *);
29
29
  void __catalyst__rt__device_release();
30
30
  void __catalyst__rt__finalize();
@@ -32,6 +32,7 @@ void __catalyst__rt__toggle_recorder(bool);
32
32
  void __catalyst__rt__print_state();
33
33
  void __catalyst__rt__print_tensor(OpaqueMemRefT *, bool);
34
34
  void __catalyst__rt__print_string(char *);
35
+ void __catalyst__rt__assert_bool(bool, char *);
35
36
  int64_t __catalyst__rt__array_get_size_1d(QirArray *);
36
37
  int8_t *__catalyst__rt__array_get_element_ptr_1d(QirArray *, int64_t);
37
38
 
@@ -47,6 +48,8 @@ RESULT *__catalyst__rt__result_get_one();
47
48
  RESULT *__catalyst__rt__result_get_zero();
48
49
 
49
50
  // Quantum Gate Set Instructions
51
+ void __catalyst__qis__SetState(MemRefT_CplxT_double_1d *, uint64_t, ...);
52
+ void __catalyst__qis__SetBasisState(MemRefT_int8_1d *, uint64_t, ...);
50
53
  void __catalyst__qis__Identity(QUBIT *, const Modifiers *);
51
54
  void __catalyst__qis__PauliX(QUBIT *, const Modifiers *);
52
55
  void __catalyst__qis__PauliY(QUBIT *, const Modifiers *);
@@ -126,6 +126,15 @@ struct MemRefT_int64_1d {
126
126
  size_t strides[1];
127
127
  };
128
128
 
129
+ // MemRefT<int64_t, dimension=1> type
130
+ struct MemRefT_int8_1d {
131
+ int8_t *data_allocated;
132
+ int8_t *data_aligned;
133
+ size_t offset;
134
+ size_t sizes[1];
135
+ size_t strides[1];
136
+ };
137
+
129
138
  // PairT<MemRefT<double, dimension=1>, MemRefT<int64, dimension=2>> type
130
139
  struct PairT_MemRefT_double_int64_1d {
131
140
  struct MemRefT_double_1d first;
@@ -16,4 +16,4 @@
16
16
  Version number (major.minor.patch[-label])
17
17
  """
18
18
 
19
- __version__ = "0.10.0"
19
+ __version__ = "0.10.2"
@@ -24,7 +24,7 @@ import itertools as it
24
24
 
25
25
  import numpy as np
26
26
 
27
- from pennylane import QubitDevice, DeviceError
27
+ from pennylane import QubitDevice, DeviceError, QuantumFunctionError
28
28
  from pennylane.ops import (
29
29
  QubitStateVector,
30
30
  BasisState,
@@ -175,31 +175,34 @@ class QrackDevice(QubitDevice):
175
175
 
176
176
  def __init__(self, wires=0, shots=None, **kwargs):
177
177
  options = dict(kwargs)
178
- if 'isStabilizerHybrid' in options:
179
- self.isStabilizerHybrid = options['isStabilizerHybrid']
180
- if 'isTensorNetwork' in options:
181
- self.isTensorNetwork = options['isTensorNetwork']
182
- if 'isSchmidtDecompose' in options:
183
- self.isSchmidtDecompose = options['isSchmidtDecompose']
184
- if 'isBinaryDecisionTree' in options:
185
- self.isBinaryDecisionTree = options['isBinaryDecisionTree']
186
- if 'isOpenCL' in options:
187
- self.isOpenCL = options['isOpenCL']
188
- if 'isHostPointer' in options:
189
- self.isHostPointer = options['isHostPointer']
190
- if 'noise' in options:
191
- self.noise = options['noise']
178
+ if "isStabilizerHybrid" in options:
179
+ self.isStabilizerHybrid = options["isStabilizerHybrid"]
180
+ if "isTensorNetwork" in options:
181
+ self.isTensorNetwork = options["isTensorNetwork"]
182
+ if "isSchmidtDecompose" in options:
183
+ self.isSchmidtDecompose = options["isSchmidtDecompose"]
184
+ if "isBinaryDecisionTree" in options:
185
+ self.isBinaryDecisionTree = options["isBinaryDecisionTree"]
186
+ if "isOpenCL" in options:
187
+ self.isOpenCL = options["isOpenCL"]
188
+ if "isHostPointer" in options:
189
+ self.isHostPointer = options["isHostPointer"]
190
+ if "noise" in options:
191
+ self.noise = options["noise"]
192
+ if (self.noise != 0) and (shots is None):
193
+ raise ValueError("Shots must be finite for noisy simulation (not analytical mode).")
192
194
  super().__init__(wires=wires, shots=shots)
193
195
  self._state = QrackSimulator(
194
196
  self.num_wires,
195
- isStabilizerHybrid = self.isStabilizerHybrid,
197
+ isStabilizerHybrid=self.isStabilizerHybrid,
196
198
  isTensorNetwork=self.isTensorNetwork,
197
199
  isSchmidtDecompose=self.isSchmidtDecompose,
198
200
  isBinaryDecisionTree=self.isBinaryDecisionTree,
199
201
  isOpenCL=self.isOpenCL,
200
202
  isHostPointer=self.isHostPointer,
201
- noise = self.noise
203
+ noise=self.noise,
202
204
  )
205
+ self._circuit = []
203
206
 
204
207
  def _reverse_state(self):
205
208
  end = self.num_wires - 1
@@ -216,7 +219,14 @@ class QrackDevice(QubitDevice):
216
219
  operations (List[pennylane.Operation]): operations to be applied
217
220
  """
218
221
 
219
- for i, op in enumerate(operations):
222
+ self._circuit = self._circuit + operations
223
+ if self.noise == 0:
224
+ self._apply()
225
+ self._circuit = []
226
+ # else: Defer application until shots or expectation values are requested
227
+
228
+ def _apply(self):
229
+ for op in self._circuit:
220
230
  if isinstance(op, QubitStateVector):
221
231
  self._apply_qubit_state_vector(op)
222
232
  elif isinstance(op, BasisState):
@@ -647,20 +657,36 @@ class QrackDevice(QubitDevice):
647
657
  # estimate the ev
648
658
  return np.mean(self.sample(observable))
649
659
 
660
+ def _generate_sample(self):
661
+ rev_sample = self._state.m_all()
662
+ sample = 0
663
+ for i in range(self.num_wires):
664
+ if (rev_sample & (1 << i)) > 0:
665
+ sample |= 1 << (self.num_wires - (i + 1))
666
+ return sample
667
+
650
668
  def generate_samples(self):
651
669
  if self.shots is None:
652
- raise qml.QuantumFunctionError(
670
+ raise QuantumFunctionError(
653
671
  "The number of shots has to be explicitly set on the device "
654
672
  "when using sample-based measurements."
655
673
  )
656
674
 
675
+ if self.noise != 0:
676
+ samples = []
677
+ for _ in range(self.shots):
678
+ self._state.reset_all()
679
+ self._apply()
680
+ samples.append(self._generate_sample())
681
+ self._samples = QubitDevice.states_to_binary(np.array(samples), self.num_wires)
682
+ self._circuit = []
683
+
684
+ return self._samples
685
+
657
686
  if self.shots == 1:
658
- rev_sample = self._state.m_all()
659
- sample = 0
660
- for i in range(self.num_wires):
661
- if (rev_sample & (1 << i)) > 0:
662
- sample |= 1 << (self.num_wires - (i + 1))
663
- self._samples = QubitDevice.states_to_binary(np.array([sample]), self.num_wires)
687
+ self._samples = QubitDevice.states_to_binary(
688
+ np.array([self._generate_sample()]), self.num_wires
689
+ )
664
690
 
665
691
  return self._samples
666
692
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pennylane-qrack
3
- Version: 0.10.0
3
+ Version: 0.10.2
4
4
  Summary: PennyLane plugin for Qrack.
5
5
  Home-page: http://github.com/vm6502q
6
6
  Maintainer: vm6502q
@@ -19,10 +19,11 @@ import subprocess
19
19
  from setuptools import setup
20
20
  from setuptools.command.build_py import build_py
21
21
 
22
+
22
23
  class Build(build_py):
23
24
  def run(self):
24
25
  protoc_command = ["make", "build-deps"]
25
- if os.name != 'nt':
26
+ if os.name != "nt":
26
27
  if subprocess.call(protoc_command) != 0:
27
28
  sys.exit(-1)
28
29
  super().run()
@@ -31,11 +32,7 @@ class Build(build_py):
31
32
  with open("./pennylane_qrack/_version.py") as f:
32
33
  (version,) = re.findall('__version__ = "(.*)"', f.read())
33
34
 
34
- requirements = [
35
- "pennylane>=0.32",
36
- "pyqrack>=1.30.0",
37
- "numpy>=1.16"
38
- ]
35
+ requirements = ["pennylane>=0.32", "pyqrack>=1.30.0", "numpy>=1.16"]
39
36
 
40
37
  info = {
41
38
  "name": "pennylane-qrack",
@@ -45,11 +42,9 @@ info = {
45
42
  "url": "http://github.com/vm6502q",
46
43
  "license": "Apache License 2.0",
47
44
  "packages": ["pennylane_qrack"],
48
- "cmdclass": { 'build_py': Build },
45
+ "cmdclass": {"build_py": Build},
49
46
  "entry_points": {
50
- "pennylane.plugins": [
51
- "qrack.simulator = pennylane_qrack.qrack_device:QrackDevice"
52
- ]
47
+ "pennylane.plugins": ["qrack.simulator = pennylane_qrack.qrack_device:QrackDevice"]
53
48
  },
54
49
  "description": "PennyLane plugin for Qrack.",
55
50
  "long_description": open("README.rst").read(),
@@ -260,9 +260,7 @@ class TestStateApply:
260
260
 
261
261
  @pytest.mark.parametrize("device_wires", [3, 4, 5])
262
262
  @pytest.mark.parametrize("op_wires", [[0], [2], [0, 1], [1, 0], [2, 0]])
263
- def test_qubit_state_vector_on_wires_subset(
264
- self, init_state, device_wires, op_wires, tol
265
- ):
263
+ def test_qubit_state_vector_on_wires_subset(self, init_state, device_wires, op_wires, tol):
266
264
  """Test QubitStateVector application on a subset of device wires"""
267
265
  dev = QrackDevice(device_wires, isOpenCL=False)
268
266
  state = init_state(len(op_wires))
@@ -314,7 +312,7 @@ class TestStateApply:
314
312
  qml.StatePrep(state, wires=[0])
315
313
  qml.apply(op)
316
314
  return qml.probs()
317
-
315
+
318
316
  dev._obs_queue = []
319
317
 
320
318
  res = circuit()
@@ -352,7 +350,7 @@ class TestStateApply:
352
350
  qml.StatePrep(state, wires=[0])
353
351
  qml.apply(op)
354
352
  return qml.probs()
355
-
353
+
356
354
  dev._obs_queue = []
357
355
 
358
356
  res = circuit()
@@ -364,9 +362,7 @@ class TestStateApply:
364
362
  @pytest.mark.parametrize("theta", [0.5432, -0.232])
365
363
  @pytest.mark.parametrize("omega", [1.213, -0.221])
366
364
  @pytest.mark.parametrize("op,func", single_qubit_three_param)
367
- def test_single_qubit_three_parameters(
368
- self, init_state, op, func, phi, theta, omega, tol
369
- ):
365
+ def test_single_qubit_three_parameters(self, init_state, op, func, phi, theta, omega, tol):
370
366
  """Test PauliX application"""
371
367
  dev = QrackDevice(1, isOpenCL=False)
372
368
  state = init_state(1)
@@ -383,14 +379,13 @@ class TestStateApply:
383
379
  @pytest.mark.parametrize("theta", [0.5432, -0.232])
384
380
  @pytest.mark.parametrize("omega", [1.213, -0.221])
385
381
  @pytest.mark.parametrize("op,func", single_qubit_three_param)
386
- def test_single_qubit_three_parameters_qjit(
387
- self, init_state, op, func, phi, theta, omega, tol
388
- ):
382
+ def test_single_qubit_three_parameters_qjit(self, init_state, op, func, phi, theta, omega, tol):
389
383
  """Test PauliX application"""
390
384
  dev = QrackDevice(1, isOpenCL=False)
391
385
  state = init_state(1)
392
386
 
393
387
  op.data = [phi, theta, omega]
388
+
394
389
  @qjit
395
390
  @qml.qnode(dev)
396
391
  def circuit():
@@ -430,6 +425,7 @@ class TestStateApply:
430
425
  qml.StatePrep(state, wires=[0, 1])
431
426
  qml.apply(op)
432
427
  return qml.probs()
428
+
433
429
  dev._obs_queue = []
434
430
 
435
431
  res = circuit()
@@ -462,12 +458,14 @@ class TestStateApply:
462
458
  state = init_state(N)
463
459
 
464
460
  op = qml.QubitUnitary(mat, wires=list(range(N)))
461
+
465
462
  @qjit
466
463
  @qml.qnode(dev)
467
464
  def circuit():
468
465
  qml.StatePrep(state, wires=list(range(N)))
469
466
  qml.apply(op)
470
467
  return qml.probs()
468
+
471
469
  dev._obs_queue = []
472
470
 
473
471
  res = circuit()
@@ -506,6 +504,7 @@ class TestStateApply:
506
504
  qml.StatePrep(state, wires=[0, 1, 2])
507
505
  qml.apply(op)
508
506
  return qml.probs()
507
+
509
508
  dev._obs_queue = []
510
509
 
511
510
  res = circuit()
@@ -549,6 +548,7 @@ class TestStateApply:
549
548
  state = init_state(2)
550
549
 
551
550
  op.data = [theta]
551
+
552
552
  @qjit
553
553
  @qml.qnode(dev)
554
554
  def circuit():
@@ -567,9 +567,7 @@ class TestStateApply:
567
567
  @pytest.mark.parametrize("theta", [0.5432, -0.232])
568
568
  @pytest.mark.parametrize("omega", [1.213, -0.221])
569
569
  @pytest.mark.parametrize("op,func", two_qubit_three_param)
570
- def test_two_qubit_three_parameters(
571
- self, init_state, op, func, phi, theta, omega, tol
572
- ):
570
+ def test_two_qubit_three_parameters(self, init_state, op, func, phi, theta, omega, tol):
573
571
  """Test parametrized two qubit gates application"""
574
572
  dev = QrackDevice(2, isOpenCL=False)
575
573
  state = init_state(2)
@@ -588,9 +586,7 @@ class TestStateApply:
588
586
  """Test that apply fails for incorrect state preparation."""
589
587
  dev = QrackDevice(2, isOpenCL=False)
590
588
 
591
- with pytest.raises(
592
- ValueError, match="Sum of amplitudes-squared does not equal one."
593
- ):
589
+ with pytest.raises(ValueError, match="Sum of amplitudes-squared does not equal one."):
594
590
  dev.apply([qml.QubitStateVector(np.array([1, -1]), wires=[0])])
595
591
 
596
592
  with pytest.raises(
@@ -17,6 +17,7 @@ import pennylane as qml
17
17
  from pennylane_qrack.qrack_device import QrackDevice
18
18
  from catalyst import qjit
19
19
 
20
+
20
21
  class TestIntegration:
21
22
  """Some basic integration tests."""
22
23