pyqrack-cuda 1.40.3__tar.gz → 1.41.1__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 (24) hide show
  1. {pyqrack_cuda-1.40.3/pyqrack_cuda.egg-info → pyqrack_cuda-1.41.1}/PKG-INFO +1 -1
  2. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack/__init__.py +1 -0
  3. pyqrack_cuda-1.41.1/pyqrack/qrack_neuron_torch_layer.py +121 -0
  4. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1/pyqrack_cuda.egg-info}/PKG-INFO +1 -1
  5. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack_cuda.egg-info/SOURCES.txt +1 -0
  6. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/setup.py +1 -1
  7. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/LICENSE +0 -0
  8. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/MANIFEST.in +0 -0
  9. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/Makefile +0 -0
  10. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/README.md +0 -0
  11. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyproject.toml +0 -0
  12. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack/neuron_activation_fn.py +0 -0
  13. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack/pauli.py +0 -0
  14. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack/qrack_circuit.py +0 -0
  15. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack/qrack_neuron.py +0 -0
  16. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack/qrack_simulator.py +0 -0
  17. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack/qrack_system/__init__.py +0 -0
  18. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack/qrack_system/qrack_system.py +0 -0
  19. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack/quimb_circuit_type.py +0 -0
  20. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack_cuda.egg-info/dependency_links.txt +0 -0
  21. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack_cuda.egg-info/not-zip-safe +0 -0
  22. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack_cuda.egg-info/requires.txt +0 -0
  23. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/pyqrack_cuda.egg-info/top_level.txt +0 -0
  24. {pyqrack_cuda-1.40.3 → pyqrack_cuda-1.41.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyqrack-cuda
3
- Version: 1.40.3
3
+ Version: 1.41.1
4
4
  Summary: pyqrack - Pure Python vm6502q/qrack Wrapper
5
5
  Home-page: https://github.com/vm6502q/pyqrack
6
6
  Author: Daniel Strano
@@ -6,6 +6,7 @@
6
6
  from .qrack_system import QrackSystem, Qrack
7
7
  from .qrack_simulator import QrackSimulator
8
8
  from .qrack_neuron import QrackNeuron
9
+ from .qrack_neuron_torch_layer import QrackNeuronTorchLayer
9
10
  from .qrack_circuit import QrackCircuit
10
11
  from .pauli import Pauli
11
12
  from .neuron_activation_fn import NeuronActivationFn
@@ -0,0 +1,121 @@
1
+ # Initial draft by Elara (OpenAI custom GPT)
2
+ # Refined and architecturally clarified by Dan Strano
3
+
4
+ _IS_TORCH_AVAILABLE = True
5
+ try:
6
+ import torch
7
+ import torch.nn as nn
8
+ from torch.autograd import Function
9
+ except ImportError:
10
+ _IS_TORCH_AVAILABLE = False
11
+
12
+ from .qrack_simulator import QrackSimulator
13
+ from .qrack_neuron import QrackNeuron
14
+ from .neuron_activation_fn import NeuronActivationFn
15
+
16
+ from itertools import chain, combinations
17
+
18
+
19
+ # From https://stackoverflow.com/questions/1482308/how-to-get-all-subsets-of-a-set-powerset#answer-1482316
20
+ def powerset(iterable):
21
+ "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3,) (1,2,3)"
22
+ s = list(iterable)
23
+ return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
24
+
25
+
26
+ class QrackTorchNeuron(nn.Module):
27
+ def __init__(self, neuron: QrackNeuron) -> None:
28
+ super().__init__()
29
+ self.neuron = neuron
30
+
31
+ def forward(self, x):
32
+ neuron = self.neuron
33
+ neuron.predict(True, False)
34
+
35
+ return neuron.simulator.prob(neuron.target)
36
+
37
+
38
+ class QrackNeuronFunction(Function if _IS_TORCH_AVAILABLE else object):
39
+ @staticmethod
40
+ def forward(ctx, neuron: object):
41
+ # Save for backward
42
+ ctx.neuron = neuron
43
+
44
+ init_prob = neuron.simulator.prob(neuron.target)
45
+ neuron.predict(True, False)
46
+ final_prob = neuron.simulator.prob(neuron.target)
47
+ ctx.delta = final_prob - init_prob
48
+
49
+ return torch.tensor([ctx.delta], dtype=torch.float32) if _IS_TORCH_AVAILABLE else ctx.delta
50
+
51
+ @staticmethod
52
+ def backward(ctx, grad_output):
53
+ neuron = ctx.neuron
54
+
55
+ pre_unpredict = neuron.simulator.prob(neuron.output_id)
56
+ neuron.unpredict()
57
+ post_unpredict = neuron.simulator.prob(neuron.output_id)
58
+ reverse_delta = pre_unpredict - post_unpredict
59
+
60
+ grad = reverse_delta - ctx.delta
61
+
62
+ return torch.tensor([grad], dtype=torch.float32) if _IS_TORCH_AVAILABLE else grad
63
+
64
+
65
+ class QrackNeuronTorchLayer(nn.Module if _IS_TORCH_AVAILABLE else object):
66
+ def __init__(self, simulator: object, input_indices: list[int], output_size: int, parameters: list[float] = None,
67
+ activation: int = int(NeuronActivationFn.Generalized_Logistic)):
68
+ super(QrackNeuronTorchLayer, self).__init__()
69
+ self.simulator = simulator
70
+ self.input_indices = input_indices
71
+ self.output_size = output_size
72
+ self.activation = NeuronActivationFn(activation)
73
+ self.fn = QrackNeuronFunction.apply if _IS_TORCH_AVAILABLE else lambda x: QrackNeuronFunction.forward(object(), x)
74
+
75
+ # Create neurons from all powerset input combinations, projecting to coherent output qubits
76
+ self.neurons = nn.ModuleList([
77
+ QrackTorchNeuron(QrackNeuron(simulator, list(input_subset), len(input_indices) + output_id, activation))
78
+ for input_subset in powerset(input_indices)
79
+ for output_id in range(output_size)
80
+ ])
81
+
82
+ # Set Qrack's internal parameters:
83
+ param_count = 0
84
+ for neuron_wrapper in self.neurons:
85
+ neuron = neuron_wrapper.neuron
86
+ p_count = 1 << len(neuron.controls)
87
+ neuron.set_angles(parameters[param_count:(param_count+p_count+1)] if parameters else ([0.0] * p_count))
88
+ param_count += p_count
89
+
90
+ self.weights = nn.ParameterList()
91
+ for pid in range(param_count):
92
+ self.weights.append(nn.Parameter(torch.tensor(parameters[pid] if parameters else 0.0)))
93
+
94
+ def forward(self, _):
95
+ # Assume quantum outputs should overwrite the simulator state
96
+ for output_id in range(self.output_size):
97
+ if self.simulator.m(len(self.input_indices) + output_id):
98
+ self.simulator.x(output_id)
99
+ self.simulator.h(output_id)
100
+
101
+ # Set Qrack's internal parameters:
102
+ param_count = 0
103
+ for neuron_wrapper in self.neurons:
104
+ neuron = neuron_wrapper.neuron
105
+ p_count = 1 << len(neuron.controls)
106
+ angles = [w.item() for w in self.weights[param_count:(param_count+p_count)]]
107
+ neuron.set_angles(angles)
108
+ param_count += p_count
109
+
110
+ # Assume quantum inputs already loaded into simulator state
111
+ for neuron_wrapper in self.neurons:
112
+ self.fn(neuron_wrapper.neuron)
113
+
114
+ # These are classical views over quantum state; simulator still maintains full coherence
115
+ outputs = [
116
+ self.simulator.prob(len(self.input_indices) + output_id)
117
+ for output_id in range(self.output_size)
118
+ ]
119
+
120
+ return torch.tensor(outputs, dtype=torch.float32)
121
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyqrack-cuda
3
- Version: 1.40.3
3
+ Version: 1.41.1
4
4
  Summary: pyqrack - Pure Python vm6502q/qrack Wrapper
5
5
  Home-page: https://github.com/vm6502q/pyqrack
6
6
  Author: Daniel Strano
@@ -9,6 +9,7 @@ pyqrack/neuron_activation_fn.py
9
9
  pyqrack/pauli.py
10
10
  pyqrack/qrack_circuit.py
11
11
  pyqrack/qrack_neuron.py
12
+ pyqrack/qrack_neuron_torch_layer.py
12
13
  pyqrack/qrack_simulator.py
13
14
  pyqrack/quimb_circuit_type.py
14
15
  pyqrack/qrack_system/__init__.py
@@ -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.40.3"
10
+ VERSION = "1.41.1"
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
File without changes