pyqrack-complex128 1.61.2__py3-none-manylinux_2_35_x86_64.whl → 1.82.1__py3-none-manylinux_2_35_x86_64.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-complex128 might be problematic. Click here for more details.

pyqrack/__init__.py CHANGED
@@ -10,8 +10,8 @@ from .qrack_ace_backend import QrackAceBackend
10
10
  from .qrack_circuit import QrackCircuit
11
11
  from .qrack_neuron import QrackNeuron
12
12
  from .qrack_neuron_torch_layer import (
13
- QrackTorchNeuron,
14
- QrackNeuronFunction,
13
+ QrackNeuronTorch,
14
+ QrackNeuronTorchFunction,
15
15
  QrackNeuronTorchLayer,
16
16
  )
17
17
  from .qrack_simulator import QrackSimulator
@@ -139,6 +139,12 @@ class LHVQubit:
139
139
  new_y = 2 * (rho_prime[0][1].imag - rho_prime[1][0].imag)
140
140
  new_z = 2 * rho_prime[0][0].real - 1 # since Tr(ρ') = 1
141
141
 
142
+ p = math.sqrt(new_x**2 + new_y**2 + new_z**2)
143
+
144
+ new_x /= p
145
+ new_y /= p
146
+ new_z /= p
147
+
142
148
  self.bloch = [new_x, new_y, new_z]
143
149
 
144
150
  def prob(self, basis=Pauli.PauliZ):
@@ -218,9 +224,7 @@ class QrackAceBackend:
218
224
  isPaged=True,
219
225
  isCpuGpuHybrid=True,
220
226
  isOpenCL=True,
221
- isHostPointer=(
222
- True if os.environ.get("PYQRACK_HOST_POINTER_DEFAULT_ON") else False
223
- ),
227
+ isHostPointer=(True if os.environ.get("PYQRACK_HOST_POINTER_DEFAULT_ON") else False),
224
228
  noise=0,
225
229
  toClone=None,
226
230
  ):
@@ -273,7 +277,7 @@ class QrackAceBackend:
273
277
  self._is_row_long_range[-1] = False
274
278
  sim_count = col_patch_count * row_patch_count
275
279
 
276
- self._qubit_dict = {}
280
+ self._qubits = []
277
281
  sim_counts = [0] * sim_count
278
282
  sim_id = 0
279
283
  tot_qubits = 0
@@ -288,11 +292,7 @@ class QrackAceBackend:
288
292
  sim_counts[t_sim_id] += 1
289
293
 
290
294
  qubit.append(
291
- LHVQubit(
292
- toClone=(
293
- toClone._qubit_dict[tot_qubits][2] if toClone else None
294
- )
295
- )
295
+ LHVQubit(toClone=(toClone._qubits[tot_qubits][2] if toClone else None))
296
296
  )
297
297
 
298
298
  if (not c) and (not r):
@@ -307,7 +307,7 @@ class QrackAceBackend:
307
307
  if not c:
308
308
  sim_id = (sim_id + 1) % sim_count
309
309
 
310
- self._qubit_dict[tot_qubits] = qubit
310
+ self._qubits.append(qubit)
311
311
  tot_qubits += 1
312
312
 
313
313
  self.sim = []
@@ -424,9 +424,10 @@ class QrackAceBackend:
424
424
  self._qec_x(c)
425
425
 
426
426
  def _unpack(self, lq):
427
- return self._qubit_dict[lq]
427
+ return self._qubits[lq]
428
428
 
429
- def _get_qb_lhv_indices(self, hq):
429
+ @staticmethod
430
+ def _get_qb_lhv_indices(hq):
430
431
  qb = []
431
432
  if len(hq) < 2:
432
433
  qb = [0]
@@ -440,15 +441,16 @@ class QrackAceBackend:
440
441
 
441
442
  return qb, lhv
442
443
 
443
- def _get_lhv_bloch_angles(self, sim):
444
+ @staticmethod
445
+ def _get_lhv_bloch_angles(sim):
444
446
  # Z axis
445
- z = 1 - 2 * sim.prob(Pauli.PauliZ)
447
+ z = sim.bloch[2]
446
448
 
447
449
  # X axis
448
- x = 1 - 2 * sim.prob(Pauli.PauliX)
450
+ x = sim.bloch[0]
449
451
 
450
452
  # Y axis
451
- y = 1 - 2 * sim.prob(Pauli.PauliY)
453
+ y = sim.bloch[1]
452
454
 
453
455
  inclination = math.atan2(math.sqrt(x**2 + y**2), z)
454
456
  azimuth = math.atan2(y, x)
@@ -480,9 +482,7 @@ class QrackAceBackend:
480
482
 
481
483
  return azimuth, inclination
482
484
 
483
- def _rotate_to_bloch(
484
- self, hq, delta_azimuth, delta_inclination
485
- ):
485
+ def _rotate_to_bloch(self, hq, delta_azimuth, delta_inclination):
486
486
  sim = self.sim[hq[0]]
487
487
  q = hq[1]
488
488
 
@@ -499,10 +499,8 @@ class QrackAceBackend:
499
499
 
500
500
  sim.mtrx([m00, m01, m10, m11], q)
501
501
 
502
-
503
- def _rotate_lhv_to_bloch(
504
- self, sim, delta_azimuth, delta_inclination
505
- ):
502
+ @staticmethod
503
+ def _rotate_lhv_to_bloch(sim, delta_azimuth, delta_inclination):
506
504
  # Apply rotation as "Azimuth, Inclination" (AI)
507
505
  cosA = math.cos(delta_azimuth)
508
506
  sinA = math.sin(delta_azimuth)
@@ -516,14 +514,13 @@ class QrackAceBackend:
516
514
 
517
515
  sim.mtrx([m00, m01, m10, m11])
518
516
 
519
-
520
517
  def _correct(self, lq, phase=False, skip_rotation=False):
521
518
  hq = self._unpack(lq)
522
519
 
523
520
  if len(hq) == 1:
524
521
  return
525
522
 
526
- qb, lhv = self._get_qb_lhv_indices(hq)
523
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
527
524
 
528
525
  if phase:
529
526
  for q in qb:
@@ -542,9 +539,7 @@ class QrackAceBackend:
542
539
  self.sim[hq[4][0]].prob(hq[4][1]),
543
540
  ]
544
541
  # Balancing suggestion from Elara (the custom OpenAI GPT)
545
- prms = math.sqrt(
546
- (p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7
547
- )
542
+ prms = math.sqrt((p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7)
548
543
  qrms = math.sqrt(
549
544
  (
550
545
  (1 - p[0]) ** 2
@@ -572,13 +567,15 @@ class QrackAceBackend:
572
567
  a, i = [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]
573
568
  a[0], i[0] = self._get_bloch_angles(hq[0])
574
569
  a[1], i[1] = self._get_bloch_angles(hq[1])
575
- a[2], i[2] = self._get_lhv_bloch_angles(hq[2])
570
+ a[2], i[2] = QrackAceBackend._get_lhv_bloch_angles(hq[2])
576
571
  a[3], i[3] = self._get_bloch_angles(hq[3])
577
572
  a[4], i[4] = self._get_bloch_angles(hq[4])
578
573
 
579
574
  a_target = 0
580
575
  i_target = 0
581
576
  for x in range(5):
577
+ if x == 2:
578
+ continue
582
579
  a_target += a[x]
583
580
  i_target += i[x]
584
581
 
@@ -586,7 +583,9 @@ class QrackAceBackend:
586
583
  i_target /= 5
587
584
  for x in range(5):
588
585
  if x == 2:
589
- self._rotate_lhv_to_bloch(hq[x], a_target - a[x], i_target - i[x])
586
+ QrackAceBackend._rotate_lhv_to_bloch(
587
+ hq[x], a_target - a[x], i_target - i[x]
588
+ )
590
589
  else:
591
590
  self._rotate_to_bloch(hq[x], a_target - a[x], i_target - i[x])
592
591
 
@@ -613,11 +612,13 @@ class QrackAceBackend:
613
612
  a, i = [0, 0, 0], [0, 0, 0]
614
613
  a[0], i[0] = self._get_bloch_angles(hq[0])
615
614
  a[1], i[1] = self._get_bloch_angles(hq[1])
616
- a[2], i[2] = self._get_lhv_bloch_angles(hq[2])
615
+ a[2], i[2] = QrackAceBackend._get_lhv_bloch_angles(hq[2])
617
616
 
618
617
  a_target = 0
619
618
  i_target = 0
620
619
  for x in range(3):
620
+ if x == 2:
621
+ continue
621
622
  a_target += a[x]
622
623
  i_target += i[x]
623
624
 
@@ -625,7 +626,9 @@ class QrackAceBackend:
625
626
  i_target /= 3
626
627
  for x in range(3):
627
628
  if x == 2:
628
- self._rotate_lhv_to_bloch(hq[x], a_target - a[x], i_target - i[x])
629
+ QrackAceBackend._rotate_lhv_to_bloch(
630
+ hq[x], a_target - a[x], i_target - i[x]
631
+ )
629
632
  else:
630
633
  self._rotate_to_bloch(hq[x], a_target - a[x], i_target - i[x])
631
634
 
@@ -636,6 +639,29 @@ class QrackAceBackend:
636
639
  b = hq[lhv]
637
640
  b.h()
638
641
 
642
+ def apply_magnetic_bias(self, q, b):
643
+ if b == 0:
644
+ return
645
+ b = math.exp(b)
646
+ for x in q:
647
+ hq = self._unpack(x)
648
+ for c in range(len(hq)):
649
+ h = hq[c]
650
+ if c == 2:
651
+ a, i = QrackAceBackend._get_lhv_bloch_angles(h)
652
+ QrackAceBackend._rotate_lhv_to_bloch(
653
+ h,
654
+ math.atan(math.tan(a) * b) - a,
655
+ math.atan(math.tan(i) * b) - i,
656
+ )
657
+ else:
658
+ a, i = self._get_bloch_angles(h)
659
+ self._rotate_to_bloch(
660
+ h,
661
+ math.atan(math.tan(a) * b) - a,
662
+ math.atan(math.tan(i) * b) - i,
663
+ )
664
+
639
665
  def u(self, lq, th, ph, lm):
640
666
  hq = self._unpack(lq)
641
667
  if len(hq) < 2:
@@ -643,7 +669,7 @@ class QrackAceBackend:
643
669
  self.sim[b[0]].u(b[1], th, ph, lm)
644
670
  return
645
671
 
646
- qb, lhv = self._get_qb_lhv_indices(hq)
672
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
647
673
 
648
674
  for q in qb:
649
675
  b = hq[q]
@@ -662,7 +688,7 @@ class QrackAceBackend:
662
688
  self.sim[b[0]].r(p, th, b[1])
663
689
  return
664
690
 
665
- qb, lhv = self._get_qb_lhv_indices(hq)
691
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
666
692
 
667
693
  for q in qb:
668
694
  b = hq[q]
@@ -690,7 +716,7 @@ class QrackAceBackend:
690
716
 
691
717
  self._correct(lq)
692
718
 
693
- qb, lhv = self._get_qb_lhv_indices(hq)
719
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
694
720
 
695
721
  for q in qb:
696
722
  b = hq[q]
@@ -708,7 +734,7 @@ class QrackAceBackend:
708
734
  self.sim[b[0]].s(b[1])
709
735
  return
710
736
 
711
- qb, lhv = self._get_qb_lhv_indices(hq)
737
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
712
738
 
713
739
  for q in qb:
714
740
  b = hq[q]
@@ -724,7 +750,7 @@ class QrackAceBackend:
724
750
  self.sim[b[0]].adjs(b[1])
725
751
  return
726
752
 
727
- qb, lhv = self._get_qb_lhv_indices(hq)
753
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
728
754
 
729
755
  for q in qb:
730
756
  b = hq[q]
@@ -740,7 +766,7 @@ class QrackAceBackend:
740
766
  self.sim[b[0]].x(b[1])
741
767
  return
742
768
 
743
- qb, lhv = self._get_qb_lhv_indices(hq)
769
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
744
770
 
745
771
  for q in qb:
746
772
  b = hq[q]
@@ -756,7 +782,7 @@ class QrackAceBackend:
756
782
  self.sim[b[0]].y(b[1])
757
783
  return
758
784
 
759
- qb, lhv = self._get_qb_lhv_indices(hq)
785
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
760
786
 
761
787
  for q in qb:
762
788
  b = hq[q]
@@ -772,7 +798,7 @@ class QrackAceBackend:
772
798
  self.sim[b[0]].z(b[1])
773
799
  return
774
800
 
775
- qb, lhv = self._get_qb_lhv_indices(hq)
801
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
776
802
 
777
803
  for q in qb:
778
804
  b = hq[q]
@@ -788,7 +814,7 @@ class QrackAceBackend:
788
814
  self.sim[b[0]].t(b[1])
789
815
  return
790
816
 
791
- qb, lhv = self._get_qb_lhv_indices(hq)
817
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
792
818
 
793
819
  for q in qb:
794
820
  b = hq[q]
@@ -804,7 +830,7 @@ class QrackAceBackend:
804
830
  self.sim[b[0]].adjt(b[1])
805
831
  return
806
832
 
807
- qb, lhv = self._get_qb_lhv_indices(hq)
833
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
808
834
 
809
835
  for q in qb:
810
836
  b = hq[q]
@@ -826,9 +852,7 @@ class QrackAceBackend:
826
852
  gate = self.sim[sim_id].macz if anti else self.sim[sim_id].mcz
827
853
  shadow = self._anti_cz_shadow if anti else self._cz_shadow
828
854
  else:
829
- raise RuntimeError(
830
- "QrackAceBackend._get_gate() should never return identity!"
831
- )
855
+ raise RuntimeError("QrackAceBackend._get_gate() should never return identity!")
832
856
 
833
857
  return gate, shadow
834
858
 
@@ -865,11 +889,7 @@ class QrackAceBackend:
865
889
  b2 = hq2[q2]
866
890
  if b1[0] == b2[0]:
867
891
  gate_fn([b1[1]], b2[1])
868
- elif (
869
- lq1_lr
870
- or (b1[1] == b2[1])
871
- or ((len(qb1) == 2) and (b1[1] == (b2[1] & 1)))
872
- ):
892
+ elif lq1_lr or (b1[1] == b2[1]) or ((len(qb1) == 2) and (b1[1] == (b2[1] & 1))):
873
893
  shadow_fn(b1, b2)
874
894
 
875
895
  def _cpauli(self, lq1, lq2, anti, pauli):
@@ -886,8 +906,8 @@ class QrackAceBackend:
886
906
 
887
907
  self._correct(lq1)
888
908
 
889
- qb1, lhv1 = self._get_qb_lhv_indices(hq1)
890
- qb2, lhv2 = self._get_qb_lhv_indices(hq2)
909
+ qb1, lhv1 = QrackAceBackend._get_qb_lhv_indices(hq1)
910
+ qb2, lhv2 = QrackAceBackend._get_qb_lhv_indices(hq2)
891
911
  # Apply cross coupling on hardware qubits first
892
912
  self._apply_coupling(pauli, anti, qb1, lhv1, hq1, qb2, lhv2, hq2, lq1_lr)
893
913
  # Apply coupling to the local-hidden-variable target
@@ -999,9 +1019,7 @@ class QrackAceBackend:
999
1019
  self.sim[hq[4][0]].prob(hq[4][1]),
1000
1020
  ]
1001
1021
  # Balancing suggestion from Elara (the custom OpenAI GPT)
1002
- prms = math.sqrt(
1003
- (p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7
1004
- )
1022
+ prms = math.sqrt((p[0] ** 2 + p[1] ** 2 + 3 * (p[2] ** 2) + p[3] ** 2 + p[4] ** 2) / 7)
1005
1023
  qrms = math.sqrt(
1006
1024
  (
1007
1025
  (1 - p[0]) ** 2
@@ -1034,7 +1052,7 @@ class QrackAceBackend:
1034
1052
  p = self.prob(lq)
1035
1053
  result = ((p + self._epsilon) >= 1) or (random.random() < p)
1036
1054
 
1037
- qb, lhv = self._get_qb_lhv_indices(hq)
1055
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
1038
1056
 
1039
1057
  for q in qb:
1040
1058
  b = hq[q]
@@ -1060,7 +1078,7 @@ class QrackAceBackend:
1060
1078
 
1061
1079
  self._correct(lq)
1062
1080
 
1063
- qb, lhv = self._get_qb_lhv_indices(hq)
1081
+ qb, lhv = QrackAceBackend._get_qb_lhv_indices(hq)
1064
1082
 
1065
1083
  for q in qb:
1066
1084
  b = hq[q]
@@ -1153,17 +1171,11 @@ class QrackAceBackend:
1153
1171
  (-1 * float(operation.params[1])) + math.pi / 2,
1154
1172
  )
1155
1173
  elif name == "rx":
1156
- self._sim.r(
1157
- Pauli.PauliX, float(operation.params[0]), operation.qubits[0]._index
1158
- )
1174
+ self._sim.r(Pauli.PauliX, float(operation.params[0]), operation.qubits[0]._index)
1159
1175
  elif name == "ry":
1160
- self._sim.r(
1161
- Pauli.PauliY, float(operation.params[0]), operation.qubits[0]._index
1162
- )
1176
+ self._sim.r(Pauli.PauliY, float(operation.params[0]), operation.qubits[0]._index)
1163
1177
  elif name == "rz":
1164
- self._sim.r(
1165
- Pauli.PauliZ, float(operation.params[0]), operation.qubits[0]._index
1166
- )
1178
+ self._sim.r(Pauli.PauliZ, float(operation.params[0]), operation.qubits[0]._index)
1167
1179
  elif name == "h":
1168
1180
  self._sim.h(operation.qubits[0]._index)
1169
1181
  elif name == "x":
@@ -1228,9 +1240,9 @@ class QrackAceBackend:
1228
1240
  cregbit = clbit
1229
1241
 
1230
1242
  regbit = 1 << cregbit
1231
- self._classical_register = (
1232
- self._classical_register & (~regbit)
1233
- ) | (qubit_outcome << cregbit)
1243
+ self._classical_register = (self._classical_register & (~regbit)) | (
1244
+ qubit_outcome << cregbit
1245
+ )
1234
1246
 
1235
1247
  elif name == "bfunc":
1236
1248
  mask = int(operation.mask, 16)
@@ -1345,9 +1357,7 @@ class QrackAceBackend:
1345
1357
  if operation.name == "id" or operation.name == "barrier":
1346
1358
  continue
1347
1359
 
1348
- if is_initializing and (
1349
- (operation.name == "measure") or (operation.name == "reset")
1350
- ):
1360
+ if is_initializing and ((operation.name == "measure") or (operation.name == "reset")):
1351
1361
  continue
1352
1362
 
1353
1363
  is_initializing = False
@@ -1405,14 +1415,13 @@ class QrackAceBackend:
1405
1415
  self._sample_cregbits = []
1406
1416
 
1407
1417
  if self._sample_measure and (len(self._sample_qubits) > 0):
1408
- _data = self._add_sample_measure(
1409
- self._sample_qubits, self._sample_clbits, self._shots
1410
- )
1418
+ _data = self._add_sample_measure(self._sample_qubits, self._sample_clbits, self._shots)
1411
1419
 
1412
1420
  del self._sim
1413
1421
 
1414
1422
  return _data
1415
1423
 
1424
+ @staticmethod
1416
1425
  def get_qiskit_basis_gates():
1417
1426
  return [
1418
1427
  "id",
@@ -1497,17 +1506,13 @@ class QrackAceBackend:
1497
1506
  noise_model.add_quantum_error(depolarizing_error(y, 2), "cx", [a, b])
1498
1507
  noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
1499
1508
  noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
1500
- noise_model.add_quantum_error(
1501
- depolarizing_error(y_swap, 2), "swap", [a, b]
1502
- )
1509
+ noise_model.add_quantum_error(depolarizing_error(y_swap, 2), "swap", [a, b])
1503
1510
  else:
1504
1511
  y_cy = 1 - (1 - y) ** 2
1505
1512
  y_swap = 1 - (1 - y) ** 3
1506
1513
  noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cx", [a, b])
1507
1514
  noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
1508
1515
  noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
1509
- noise_model.add_quantum_error(
1510
- depolarizing_error(y_swap, 2), "swap", [a, b]
1511
- )
1516
+ noise_model.add_quantum_error(depolarizing_error(y_swap, 2), "swap", [a, b])
1512
1517
 
1513
1518
  return noise_model
pyqrack/qrack_circuit.py CHANGED
@@ -59,7 +59,7 @@ class QrackCircuit:
59
59
  self.cid = Qrack.qrack_lib.qcircuit_inverse(clone_cid)
60
60
  elif len(past_light_cone) > 0:
61
61
  self.cid = Qrack.qrack_lib.qcircuit_past_light_cone(
62
- clone_cid, len(past_light_cone), self._ulonglong_byref(past_light_cone)
62
+ clone_cid, len(past_light_cone), QrackCircuit._ulonglong_byref(past_light_cone)
63
63
  )
64
64
  else:
65
65
  self.cid = Qrack.qrack_lib.init_qcircuit_clone(clone_cid)
@@ -69,16 +69,20 @@ class QrackCircuit:
69
69
  Qrack.qrack_lib.destroy_qcircuit(self.cid)
70
70
  self.cid = None
71
71
 
72
- def _ulonglong_byref(self, a):
72
+ @staticmethod
73
+ def _ulonglong_byref(a):
73
74
  return (ctypes.c_ulonglong * len(a))(*a)
74
75
 
75
- def _double_byref(self, a):
76
+ @staticmethod
77
+ def _double_byref(a):
76
78
  return (ctypes.c_double * len(a))(*a)
77
79
 
78
- def _complex_byref(self, a):
80
+ @staticmethod
81
+ def _complex_byref(a):
79
82
  t = [(c.real, c.imag) for c in a]
80
- return self._double_byref([float(item) for sublist in t for item in sublist])
83
+ return QrackCircuit._double_byref([float(item) for sublist in t for item in sublist])
81
84
 
85
+ @staticmethod
82
86
  def _mtrx_to_u4(m):
83
87
  nrm = abs(m[0])
84
88
  if (nrm * nrm) < sys.float_info.epsilon:
@@ -103,6 +107,7 @@ class QrackCircuit:
103
107
 
104
108
  return th, ph, lm, np.angle(phase)
105
109
 
110
+ @staticmethod
106
111
  def _u3_to_mtrx(params):
107
112
  th = float(params[0])
108
113
  ph = float(params[1])
@@ -115,6 +120,7 @@ class QrackCircuit:
115
120
 
116
121
  return [c + 0j, -el * s, ep * s, ep * el * c]
117
122
 
123
+ @staticmethod
118
124
  def _u4_to_mtrx(params):
119
125
  m = QrackCircuit._u3_to_mtrx(params)
120
126
  g = np.exp(1j * float(params[3]))
@@ -123,6 +129,7 @@ class QrackCircuit:
123
129
 
124
130
  return m
125
131
 
132
+ @staticmethod
126
133
  def _make_mtrx_unitary(m):
127
134
  return QrackCircuit._u4_to_mtrx(QrackCircuit._mtrx_to_u4(m))
128
135
 
@@ -190,7 +197,7 @@ class QrackCircuit:
190
197
  raise ValueError(
191
198
  "2x2 matrix 'm' in QrackCircuit.mtrx() must contain at least 4 elements."
192
199
  )
193
- Qrack.qrack_lib.qcircuit_append_1qb(self.cid, self._complex_byref(m), q)
200
+ Qrack.qrack_lib.qcircuit_append_1qb(self.cid, QrackCircuit._complex_byref(m), q)
194
201
 
195
202
  def ucmtrx(self, c, m, q, p):
196
203
  """Multi-controlled single-target-qubit gate
@@ -214,7 +221,7 @@ class QrackCircuit:
214
221
  "2x2 matrix 'm' in QrackCircuit.ucmtrx() must contain at least 4 elements."
215
222
  )
216
223
  Qrack.qrack_lib.qcircuit_append_mc(
217
- self.cid, self._complex_byref(m), len(c), self._ulonglong_byref(c), q, p
224
+ self.cid, QrackCircuit._complex_byref(m), len(c), QrackCircuit._ulonglong_byref(c), q, p
218
225
  )
219
226
 
220
227
  def run(self, qsim):
@@ -248,20 +255,6 @@ class QrackCircuit:
248
255
  """
249
256
  Qrack.qrack_lib.qcircuit_out_to_file(self.cid, filename.encode("utf-8"))
250
257
 
251
- def in_from_file(filename):
252
- """Read in optimized circuit from file
253
-
254
- Reads in an (optimized) circuit from a file named
255
- according to the "filename" parameter.
256
-
257
- Args:
258
- filename: Name of file
259
- """
260
- out = QrackCircuit()
261
- Qrack.qrack_lib.qcircuit_in_from_file(out.cid, filename.encode("utf-8"))
262
-
263
- return out
264
-
265
258
  def out_to_string(self):
266
259
  """Output optimized circuit to string
267
260
 
@@ -273,19 +266,6 @@ class QrackCircuit:
273
266
 
274
267
  return out.value.decode("utf-8")
275
268
 
276
- def file_gate_count(filename):
277
- """File gate count
278
-
279
- Return the count of gates in a QrackCircuit file
280
-
281
- Args:
282
- filename: Name of file
283
- """
284
- tokens = []
285
- with open(filename, "r") as file:
286
- tokens = file.read().split()
287
- return int(tokens[1])
288
-
289
269
  def to_qiskit_circuit(self):
290
270
  """Convert to a Qiskit circuit
291
271
 
@@ -302,6 +282,36 @@ class QrackCircuit:
302
282
 
303
283
  return QrackCircuit.string_to_qiskit_circuit(self.out_to_string())
304
284
 
285
+ @staticmethod
286
+ def in_from_file(filename):
287
+ """Read in optimized circuit from file
288
+
289
+ Reads in an (optimized) circuit from a file named
290
+ according to the "filename" parameter.
291
+
292
+ Args:
293
+ filename: Name of file
294
+ """
295
+ out = QrackCircuit()
296
+ Qrack.qrack_lib.qcircuit_in_from_file(out.cid, filename.encode("utf-8"))
297
+
298
+ return out
299
+
300
+ @staticmethod
301
+ def file_gate_count(filename):
302
+ """File gate count
303
+
304
+ Return the count of gates in a QrackCircuit file
305
+
306
+ Args:
307
+ filename: Name of file
308
+ """
309
+ tokens = []
310
+ with open(filename, "r") as file:
311
+ tokens = file.read().split()
312
+ return int(tokens[1])
313
+
314
+ @staticmethod
305
315
  def file_to_qiskit_circuit(filename):
306
316
  """Convert an output file to a Qiskit circuit
307
317
 
@@ -325,6 +335,7 @@ class QrackCircuit:
325
335
  with open(filename, "r") as file:
326
336
  return QrackCircuit.string_to_qiskit_circuit(file.read())
327
337
 
338
+ @staticmethod
328
339
  def string_to_qiskit_circuit(circ_string):
329
340
  """Convert an output string to a Qiskit circuit
330
341
 
@@ -398,6 +409,7 @@ class QrackCircuit:
398
409
 
399
410
  return circ
400
411
 
412
+ @staticmethod
401
413
  def in_from_qiskit_circuit(circ):
402
414
  """Read a Qiskit circuit into a QrackCircuit
403
415
 
@@ -443,6 +455,7 @@ class QrackCircuit:
443
455
 
444
456
  return out
445
457
 
458
+ @staticmethod
446
459
  def file_to_quimb_circuit(
447
460
  filename,
448
461
  circuit_type=QuimbCircuitType.Circuit,
@@ -494,9 +507,7 @@ class QrackCircuit:
494
507
  )
495
508
  if circuit_type == QuimbCircuitType.Circuit
496
509
  else (
497
- qtn.CircuitDense(
498
- N=qcirc.num_qubits, psi0=psi0, gate_opts=gate_opts, tags=tags
499
- )
510
+ qtn.CircuitDense(N=qcirc.num_qubits, psi0=psi0, gate_opts=gate_opts, tags=tags)
500
511
  if circuit_type == QuimbCircuitType.CircuitDense
501
512
  else qtn.CircuitMPS(
502
513
  N=qcirc.num_qubits,
@@ -526,9 +537,8 @@ class QrackCircuit:
526
537
 
527
538
  return tcirc
528
539
 
529
- def file_to_tensorcircuit(
530
- filename, inputs=None, circuit_params=None, binding_params=None
531
- ):
540
+ @staticmethod
541
+ def file_to_tensorcircuit(filename, inputs=None, circuit_params=None, binding_params=None):
532
542
  """Convert an output file to a TensorCircuit circuit
533
543
 
534
544
  Reads in an (optimized) circuit from a file named
@@ -558,6 +568,7 @@ class QrackCircuit:
558
568
  qcirc, qcirc.num_qubits, inputs, circuit_params, binding_params
559
569
  )
560
570
 
571
+ @staticmethod
561
572
  def in_from_tensorcircuit(tcirc, enable_instruction=False, enable_inputs=False):
562
573
  """Convert a TensorCircuit circuit to a QrackCircuit
563
574