pyqrack-cpu 1.44.8__py3-none-win_amd64.whl → 1.44.9__py3-none-win_amd64.whl

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 pyqrack-cpu might be problematic. Click here for more details.

pyqrack/qrack_circuit.py CHANGED
@@ -45,13 +45,22 @@ class QrackCircuit:
45
45
  cid(int): Qrack ID of this circuit
46
46
  """
47
47
 
48
- def __init__(self, is_collapse = True, is_near_clifford = False, clone_cid = -1, is_inverse=False, past_light_cone = []):
48
+ def __init__(
49
+ self,
50
+ is_collapse=True,
51
+ is_near_clifford=False,
52
+ clone_cid=-1,
53
+ is_inverse=False,
54
+ past_light_cone=[],
55
+ ):
49
56
  if clone_cid < 0:
50
57
  self.cid = Qrack.qrack_lib.init_qcircuit(is_collapse, is_near_clifford)
51
58
  elif is_inverse:
52
59
  self.cid = Qrack.qrack_lib.qcircuit_inverse(clone_cid)
53
60
  elif len(past_light_cone) > 0:
54
- self.cid = Qrack.qrack_lib.qcircuit_past_light_cone(clone_cid, len(past_light_cone), self._ulonglong_byref(past_light_cone))
61
+ self.cid = Qrack.qrack_lib.qcircuit_past_light_cone(
62
+ clone_cid, len(past_light_cone), self._ulonglong_byref(past_light_cone)
63
+ )
55
64
  else:
56
65
  self.cid = Qrack.qrack_lib.init_qcircuit_clone(clone_cid)
57
66
 
@@ -74,7 +83,7 @@ class QrackCircuit:
74
83
  nrm = abs(m[0])
75
84
  if (nrm * nrm) < sys.float_info.epsilon:
76
85
  phase = 1.0 + 0.0j
77
- th = math.pi;
86
+ th = math.pi
78
87
  else:
79
88
  phase = m[0] / nrm
80
89
  if nrm > 1.0:
@@ -123,7 +132,7 @@ class QrackCircuit:
123
132
  Raises:
124
133
  RuntimeError: QrackCircuit C++ library raised an exception.
125
134
  """
126
- return QrackCircuit(clone_cid = self.cid, is_inverse = False)
135
+ return QrackCircuit(clone_cid=self.cid, is_inverse=False)
127
136
 
128
137
  def inverse(self):
129
138
  """Make a new circuit that is the exact inverse of this circuit
@@ -131,7 +140,7 @@ class QrackCircuit:
131
140
  Raises:
132
141
  RuntimeError: QrackCircuit C++ library raised an exception.
133
142
  """
134
- return QrackCircuit(clone_cid = self.cid, is_inverse = True)
143
+ return QrackCircuit(clone_cid=self.cid, is_inverse=True)
135
144
 
136
145
  def past_light_cone(self, q):
137
146
  """Make a new circuit with just this circuits' past light cone for certain qubits.
@@ -142,7 +151,7 @@ class QrackCircuit:
142
151
  Raises:
143
152
  RuntimeError: QrackCircuit C++ library raised an exception.
144
153
  """
145
- return QrackCircuit(clone_cid = self.cid, is_inverse = False, past_light_cone = q)
154
+ return QrackCircuit(clone_cid=self.cid, is_inverse=False, past_light_cone=q)
146
155
 
147
156
  def get_qubit_count(self):
148
157
  """Get count of qubits in circuit
@@ -178,7 +187,9 @@ class QrackCircuit:
178
187
  RuntimeError: QrackSimulator raised an exception.
179
188
  """
180
189
  if len(m) < 4:
181
- raise ValueError("2x2 matrix 'm' in QrackCircuit.mtrx() must contain at least 4 elements.")
190
+ raise ValueError(
191
+ "2x2 matrix 'm' in QrackCircuit.mtrx() must contain at least 4 elements."
192
+ )
182
193
  Qrack.qrack_lib.qcircuit_append_1qb(self.cid, self._complex_byref(m), q)
183
194
 
184
195
  def ucmtrx(self, c, m, q, p):
@@ -199,7 +210,9 @@ class QrackCircuit:
199
210
  RuntimeError: QrackSimulator raised an exception.
200
211
  """
201
212
  if len(m) < 4:
202
- raise ValueError("2x2 matrix 'm' in QrackCircuit.ucmtrx() must contain at least 4 elements.")
213
+ raise ValueError(
214
+ "2x2 matrix 'm' in QrackCircuit.ucmtrx() must contain at least 4 elements."
215
+ )
203
216
  Qrack.qrack_lib.qcircuit_append_mc(
204
217
  self.cid, self._complex_byref(m), len(c), self._ulonglong_byref(c), q, p
205
218
  )
@@ -233,7 +246,7 @@ class QrackCircuit:
233
246
  Args:
234
247
  filename: Name of file
235
248
  """
236
- Qrack.qrack_lib.qcircuit_out_to_file(self.cid, filename.encode('utf-8'))
249
+ Qrack.qrack_lib.qcircuit_out_to_file(self.cid, filename.encode("utf-8"))
237
250
 
238
251
  def in_from_file(filename):
239
252
  """Read in optimized circuit from file
@@ -245,7 +258,7 @@ class QrackCircuit:
245
258
  filename: Name of file
246
259
  """
247
260
  out = QrackCircuit()
248
- Qrack.qrack_lib.qcircuit_in_from_file(out.cid, filename.encode('utf-8'))
261
+ Qrack.qrack_lib.qcircuit_in_from_file(out.cid, filename.encode("utf-8"))
249
262
 
250
263
  return out
251
264
 
@@ -269,7 +282,7 @@ class QrackCircuit:
269
282
  filename: Name of file
270
283
  """
271
284
  tokens = []
272
- with open(filename, 'r') as file:
285
+ with open(filename, "r") as file:
273
286
  tokens = file.read().split()
274
287
  return int(tokens[1])
275
288
 
@@ -309,7 +322,7 @@ class QrackCircuit:
309
322
  )
310
323
 
311
324
  tokens = []
312
- with open(filename, 'r') as file:
325
+ with open(filename, "r") as file:
313
326
  return QrackCircuit.string_to_qiskit_circuit(file.read())
314
327
 
315
328
  def string_to_qiskit_circuit(circ_string):
@@ -361,8 +374,8 @@ class QrackCircuit:
361
374
 
362
375
  mtrx = []
363
376
  for _ in range(4):
364
- amp = tokens[i].replace("(","").replace(")","").split(',')
365
- mtrx.append(float(amp[0]) + float(amp[1])*1j)
377
+ amp = tokens[i].replace("(", "").replace(")", "").split(",")
378
+ mtrx.append(float(amp[0]) + float(amp[1]) * 1j)
366
379
  i += 1
367
380
 
368
381
  mtrx = QrackCircuit._make_mtrx_unitary(mtrx)
@@ -375,7 +388,7 @@ class QrackCircuit:
375
388
 
376
389
  payloads[key] = op
377
390
 
378
- gate_list=[]
391
+ gate_list = []
379
392
  for j in range(1 << control_count):
380
393
  if j in payloads:
381
394
  gate_list.append(payloads[j])
@@ -421,7 +434,12 @@ class QrackCircuit:
421
434
  if o.name in ["x", "y", "z", "u"]:
422
435
  out.mtrx(op, circ.find_bit(gate.qubits[0])[0])
423
436
  else:
424
- out.ucmtrx([circ.find_bit(gate.qubits[0])[0]], op, circ.find_bit(gate.qubits[1])[0], 1)
437
+ out.ucmtrx(
438
+ [circ.find_bit(gate.qubits[0])[0]],
439
+ op,
440
+ circ.find_bit(gate.qubits[1])[0],
441
+ 1,
442
+ )
425
443
 
426
444
  return out
427
445
 
@@ -431,9 +449,9 @@ class QrackCircuit:
431
449
  psi0=None,
432
450
  gate_opts=None,
433
451
  tags=None,
434
- psi0_dtype='complex128',
435
- psi0_tag='PSI0',
436
- bra_site_ind_id='b{}'
452
+ psi0_dtype="complex128",
453
+ psi0_tag="PSI0",
454
+ bra_site_ind_id="b{}",
437
455
  ):
438
456
  """Convert an output file to a Quimb circuit
439
457
 
@@ -464,25 +482,32 @@ class QrackCircuit:
464
482
  basis_gates = ["u", "cx"]
465
483
  qcirc = transpile(qcirc, basis_gates=basis_gates, optimization_level=3)
466
484
 
467
- tcirc = qtn.Circuit(
468
- N=qcirc.num_qubits,
469
- psi0=psi0,
470
- gate_opts=gate_opts,
471
- tags=tags,
472
- psi0_dtype=psi0_dtype,
473
- psi0_tag=psi0_tag,
474
- bra_site_ind_id=bra_site_ind_id
475
- ) if circuit_type == QuimbCircuitType.Circuit else (
476
- qtn.CircuitDense(N=qcirc.num_qubits, psi0=psi0, gate_opts=gate_opts, tags=tags) if circuit_type == QuimbCircuitType.CircuitDense else
477
- qtn.CircuitMPS(
485
+ tcirc = (
486
+ qtn.Circuit(
487
+ N=qcirc.num_qubits,
488
+ psi0=psi0,
489
+ gate_opts=gate_opts,
490
+ tags=tags,
491
+ psi0_dtype=psi0_dtype,
492
+ psi0_tag=psi0_tag,
493
+ bra_site_ind_id=bra_site_ind_id,
494
+ )
495
+ if circuit_type == QuimbCircuitType.Circuit
496
+ else (
497
+ qtn.CircuitDense(
498
+ N=qcirc.num_qubits, psi0=psi0, gate_opts=gate_opts, tags=tags
499
+ )
500
+ if circuit_type == QuimbCircuitType.CircuitDense
501
+ else qtn.CircuitMPS(
478
502
  N=qcirc.num_qubits,
479
503
  psi0=psi0,
480
504
  gate_opts=gate_opts,
481
505
  tags=tags,
482
506
  psi0_dtype=psi0_dtype,
483
507
  psi0_tag=psi0_tag,
484
- bra_site_ind_id=bra_site_ind_id
508
+ bra_site_ind_id=bra_site_ind_id,
485
509
  )
510
+ )
486
511
  )
487
512
  for gate in qcirc.data:
488
513
  o = gate.operation
@@ -491,17 +516,18 @@ class QrackCircuit:
491
516
  ph = float(o.params[1])
492
517
  lm = float(o.params[2])
493
518
 
494
- tcirc.apply_gate('U3', th, ph, lm, qcirc.find_bit(gate.qubits[0])[0])
519
+ tcirc.apply_gate("U3", th, ph, lm, qcirc.find_bit(gate.qubits[0])[0])
495
520
  else:
496
- tcirc.apply_gate('CNOT', qcirc.find_bit(gate.qubits[0])[0], qcirc.find_bit(gate.qubits[1])[0])
521
+ tcirc.apply_gate(
522
+ "CNOT",
523
+ qcirc.find_bit(gate.qubits[0])[0],
524
+ qcirc.find_bit(gate.qubits[1])[0],
525
+ )
497
526
 
498
527
  return tcirc
499
528
 
500
529
  def file_to_tensorcircuit(
501
- filename,
502
- inputs=None,
503
- circuit_params=None,
504
- binding_params=None
530
+ filename, inputs=None, circuit_params=None, binding_params=None
505
531
  ):
506
532
  """Convert an output file to a TensorCircuit circuit
507
533
 
@@ -528,9 +554,11 @@ class QrackCircuit:
528
554
  basis_gates = ["u", "cx"]
529
555
  qcirc = transpile(qcirc, basis_gates=basis_gates, optimization_level=3)
530
556
 
531
- return tc.Circuit.from_qiskit(qcirc, qcirc.num_qubits, inputs, circuit_params, binding_params)
557
+ return tc.Circuit.from_qiskit(
558
+ qcirc, qcirc.num_qubits, inputs, circuit_params, binding_params
559
+ )
532
560
 
533
- def in_from_tensorcircuit(tcirc, enable_instruction = False, enable_inputs = False):
561
+ def in_from_tensorcircuit(tcirc, enable_instruction=False, enable_inputs=False):
534
562
  """Convert a TensorCircuit circuit to a QrackCircuit
535
563
 
536
564
  Accepts a TensorCircuit circuit and outputs an equivalent QrackCircuit
pyqrack/qrack_neuron.py CHANGED
@@ -46,10 +46,10 @@ class QrackNeuron:
46
46
  simulator,
47
47
  controls,
48
48
  target,
49
- activation_fn = NeuronActivationFn.Sigmoid,
50
- alpha = 1.0,
51
- tolerance = sys.float_info.epsilon,
52
- _init = True
49
+ activation_fn=NeuronActivationFn.Sigmoid,
50
+ alpha=1.0,
51
+ tolerance=sys.float_info.epsilon,
52
+ _init=True,
53
53
  ):
54
54
  self.simulator = simulator
55
55
  self.controls = controls
@@ -61,7 +61,15 @@ class QrackNeuron:
61
61
  if not _init:
62
62
  return
63
63
 
64
- self.nid = Qrack.qrack_lib.init_qneuron(simulator.sid, len(controls), self._ulonglong_byref(controls), target, activation_fn, alpha, tolerance)
64
+ self.nid = Qrack.qrack_lib.init_qneuron(
65
+ simulator.sid,
66
+ len(controls),
67
+ self._ulonglong_byref(controls),
68
+ target,
69
+ activation_fn,
70
+ alpha,
71
+ tolerance,
72
+ )
65
73
 
66
74
  self._throw_if_error()
67
75
 
@@ -79,7 +87,14 @@ class QrackNeuron:
79
87
  Raises:
80
88
  RuntimeError: QrackNeuron C++ library raised an exception.
81
89
  """
82
- result = QrackNeuron(self.simulator, self.controls, self.target, self.activation_fn, self.alpha, self.tolerance)
90
+ result = QrackNeuron(
91
+ self.simulator,
92
+ self.controls,
93
+ self.target,
94
+ self.activation_fn,
95
+ self.alpha,
96
+ self.tolerance,
97
+ )
83
98
  self.nid = Qrack.qrack_lib.clone_qneuron(self.simulator.sid)
84
99
  self._throw_if_error()
85
100
  return result
@@ -107,7 +122,9 @@ class QrackNeuron:
107
122
  RuntimeError: QrackSimulator raised an exception.
108
123
  """
109
124
  if len(a) < (1 << len(self.controls)):
110
- raise ValueError("Angles 'a' in QrackNeuron.set_angles() must contain at least (2 ** len(self.controls)) elements.")
125
+ raise ValueError(
126
+ "Angles 'a' in QrackNeuron.set_angles() must contain at least (2 ** len(self.controls)) elements."
127
+ )
111
128
  Qrack.qrack_lib.set_qneuron_angles(self.nid, self._real1_byref(a))
112
129
  self._throw_if_error()
113
130
 
@@ -145,7 +162,7 @@ class QrackNeuron:
145
162
 
146
163
  Nonlinear activation functions can be important to neural net
147
164
  applications, like DNN. The available activation functions are
148
- enumerated in `NeuronActivationFn`.
165
+ enumerated in `NeuronActivationFn`.
149
166
 
150
167
  Raises:
151
168
  RuntimeError: QrackNeuron C++ library raised an exception.
@@ -24,7 +24,7 @@ from itertools import chain, combinations
24
24
  def powerset(iterable):
25
25
  "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3,) (1,2,3)"
26
26
  s = list(iterable)
27
- return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
27
+ return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))
28
28
 
29
29
 
30
30
  class QrackTorchNeuron(nn.Module if _IS_TORCH_AVAILABLE else object):
@@ -33,6 +33,7 @@ class QrackTorchNeuron(nn.Module if _IS_TORCH_AVAILABLE else object):
33
33
  Attributes:
34
34
  neuron(QrackNeuron): QrackNeuron backing this torch wrapper
35
35
  """
36
+
36
37
  def __init__(self, neuron: QrackNeuron):
37
38
  super().__init__()
38
39
  self.neuron = neuron
@@ -46,6 +47,7 @@ class QrackTorchNeuron(nn.Module if _IS_TORCH_AVAILABLE else object):
46
47
 
47
48
  class QrackNeuronFunction(Function if _IS_TORCH_AVAILABLE else object):
48
49
  """Static forward/backward/apply functions for QrackTorchNeuron"""
50
+
49
51
  @staticmethod
50
52
  def forward(ctx, neuron):
51
53
  # Save for backward
@@ -56,7 +58,11 @@ class QrackNeuronFunction(Function if _IS_TORCH_AVAILABLE else object):
56
58
  final_prob = neuron.simulator.prob(neuron.target)
57
59
  ctx.delta = final_prob - init_prob
58
60
 
59
- return torch.tensor([ctx.delta], dtype=torch.float32) if _IS_TORCH_AVAILABLE else ctx.delta
61
+ return (
62
+ torch.tensor([ctx.delta], dtype=torch.float32)
63
+ if _IS_TORCH_AVAILABLE
64
+ else ctx.delta
65
+ )
60
66
 
61
67
  @staticmethod
62
68
  def backward(ctx, grad_output):
@@ -69,13 +75,22 @@ class QrackNeuronFunction(Function if _IS_TORCH_AVAILABLE else object):
69
75
 
70
76
  grad = reverse_delta - ctx.delta
71
77
 
72
- return torch.tensor([grad], dtype=torch.float32) if _IS_TORCH_AVAILABLE else grad
78
+ return (
79
+ torch.tensor([grad], dtype=torch.float32) if _IS_TORCH_AVAILABLE else grad
80
+ )
73
81
 
74
82
 
75
83
  class QrackNeuronTorchLayer(nn.Module if _IS_TORCH_AVAILABLE else object):
76
84
  """Torch layer wrapper for QrackNeuron (with power set of neurons between inputs and outputs)"""
77
- def __init__(self, simulator, input_indices, output_indices,
78
- activation=int(NeuronActivationFn.Generalized_Logistic), parameters=None):
85
+
86
+ def __init__(
87
+ self,
88
+ simulator,
89
+ input_indices,
90
+ output_indices,
91
+ activation=int(NeuronActivationFn.Generalized_Logistic),
92
+ parameters=None,
93
+ ):
79
94
  """
80
95
  Initialize a QrackNeuron layer for PyTorch with a power set of neurons connecting inputs to outputs.
81
96
  The inputs and outputs must take the form of discrete, binary features (loaded manually into the backing QrackSimulator)
@@ -92,26 +107,40 @@ class QrackNeuronTorchLayer(nn.Module if _IS_TORCH_AVAILABLE else object):
92
107
  self.input_indices = input_indices
93
108
  self.output_indices = output_indices
94
109
  self.activation = NeuronActivationFn(activation)
95
- self.fn = QrackNeuronFunction.apply if _IS_TORCH_AVAILABLE else lambda x: QrackNeuronFunction.forward(object(), x)
110
+ self.fn = (
111
+ QrackNeuronFunction.apply
112
+ if _IS_TORCH_AVAILABLE
113
+ else lambda x: QrackNeuronFunction.forward(object(), x)
114
+ )
96
115
 
97
116
  # Create neurons from all powerset input combinations, projecting to coherent output qubits
98
- self.neurons = nn.ModuleList([
99
- QrackTorchNeuron(QrackNeuron(simulator, list(input_subset), output_id, activation))
100
- for input_subset in powerset(input_indices)
101
- for output_id in output_indices
102
- ])
117
+ self.neurons = nn.ModuleList(
118
+ [
119
+ QrackTorchNeuron(
120
+ QrackNeuron(simulator, list(input_subset), output_id, activation)
121
+ )
122
+ for input_subset in powerset(input_indices)
123
+ for output_id in output_indices
124
+ ]
125
+ )
103
126
 
104
127
  # Set Qrack's internal parameters:
105
128
  param_count = 0
106
129
  for neuron_wrapper in self.neurons:
107
130
  neuron = neuron_wrapper.neuron
108
131
  p_count = 1 << len(neuron.controls)
109
- neuron.set_angles(parameters[param_count:(param_count+p_count+1)] if parameters else ([0.0] * p_count))
132
+ neuron.set_angles(
133
+ parameters[param_count : (param_count + p_count + 1)]
134
+ if parameters
135
+ else ([0.0] * p_count)
136
+ )
110
137
  param_count += p_count
111
138
 
112
139
  self.weights = nn.ParameterList()
113
140
  for pid in range(param_count):
114
- self.weights.append(nn.Parameter(torch.tensor(parameters[pid] if parameters else 0.0)))
141
+ self.weights.append(
142
+ nn.Parameter(torch.tensor(parameters[pid] if parameters else 0.0))
143
+ )
115
144
 
116
145
  def forward(self, _):
117
146
  # Assume quantum outputs should overwrite the simulator state
@@ -125,7 +154,9 @@ class QrackNeuronTorchLayer(nn.Module if _IS_TORCH_AVAILABLE else object):
125
154
  for neuron_wrapper in self.neurons:
126
155
  neuron = neuron_wrapper.neuron
127
156
  p_count = 1 << len(neuron.controls)
128
- angles = [w.item() for w in self.weights[param_count:(param_count+p_count)]]
157
+ angles = [
158
+ w.item() for w in self.weights[param_count : (param_count + p_count)]
159
+ ]
129
160
  neuron.set_angles(angles)
130
161
  param_count += p_count
131
162
 
@@ -134,10 +165,6 @@ class QrackNeuronTorchLayer(nn.Module if _IS_TORCH_AVAILABLE else object):
134
165
  self.fn(neuron_wrapper.neuron)
135
166
 
136
167
  # These are classical views over quantum state; simulator still maintains full coherence
137
- outputs = [
138
- self.simulator.prob(output_id)
139
- for output_id in self.output_indices
140
- ]
168
+ outputs = [self.simulator.prob(output_id) for output_id in self.output_indices]
141
169
 
142
170
  return torch.tensor(outputs, dtype=torch.float32)
143
-