tensorcircuit-nightly 1.2.0.dev20250326__py3-none-any.whl → 1.4.0.dev20251128__py3-none-any.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 tensorcircuit-nightly might be problematic. Click here for more details.

Files changed (77) hide show
  1. tensorcircuit/__init__.py +5 -1
  2. tensorcircuit/abstractcircuit.py +4 -0
  3. tensorcircuit/analogcircuit.py +413 -0
  4. tensorcircuit/applications/layers.py +1 -1
  5. tensorcircuit/applications/van.py +1 -1
  6. tensorcircuit/backends/abstract_backend.py +312 -5
  7. tensorcircuit/backends/cupy_backend.py +3 -1
  8. tensorcircuit/backends/jax_backend.py +100 -4
  9. tensorcircuit/backends/jax_ops.py +108 -0
  10. tensorcircuit/backends/numpy_backend.py +49 -3
  11. tensorcircuit/backends/pytorch_backend.py +92 -3
  12. tensorcircuit/backends/tensorflow_backend.py +102 -3
  13. tensorcircuit/basecircuit.py +157 -98
  14. tensorcircuit/circuit.py +115 -57
  15. tensorcircuit/cloud/local.py +1 -1
  16. tensorcircuit/cloud/quafu_provider.py +1 -1
  17. tensorcircuit/cloud/tencent.py +1 -1
  18. tensorcircuit/compiler/simple_compiler.py +2 -2
  19. tensorcircuit/cons.py +105 -23
  20. tensorcircuit/densitymatrix.py +16 -11
  21. tensorcircuit/experimental.py +733 -153
  22. tensorcircuit/fgs.py +254 -73
  23. tensorcircuit/gates.py +66 -22
  24. tensorcircuit/interfaces/jax.py +5 -3
  25. tensorcircuit/interfaces/tensortrans.py +6 -2
  26. tensorcircuit/interfaces/torch.py +14 -4
  27. tensorcircuit/keras.py +3 -3
  28. tensorcircuit/mpscircuit.py +154 -65
  29. tensorcircuit/quantum.py +698 -134
  30. tensorcircuit/quditcircuit.py +733 -0
  31. tensorcircuit/quditgates.py +618 -0
  32. tensorcircuit/results/counts.py +131 -18
  33. tensorcircuit/results/readout_mitigation.py +4 -1
  34. tensorcircuit/shadows.py +1 -1
  35. tensorcircuit/simplify.py +3 -1
  36. tensorcircuit/stabilizercircuit.py +29 -17
  37. tensorcircuit/templates/__init__.py +2 -0
  38. tensorcircuit/templates/blocks.py +2 -2
  39. tensorcircuit/templates/hamiltonians.py +174 -0
  40. tensorcircuit/templates/lattice.py +1789 -0
  41. tensorcircuit/timeevol.py +896 -0
  42. tensorcircuit/translation.py +10 -3
  43. tensorcircuit/utils.py +7 -0
  44. {tensorcircuit_nightly-1.2.0.dev20250326.dist-info → tensorcircuit_nightly-1.4.0.dev20251128.dist-info}/METADATA +66 -29
  45. tensorcircuit_nightly-1.4.0.dev20251128.dist-info/RECORD +96 -0
  46. {tensorcircuit_nightly-1.2.0.dev20250326.dist-info → tensorcircuit_nightly-1.4.0.dev20251128.dist-info}/WHEEL +1 -1
  47. {tensorcircuit_nightly-1.2.0.dev20250326.dist-info → tensorcircuit_nightly-1.4.0.dev20251128.dist-info}/top_level.txt +0 -1
  48. tensorcircuit_nightly-1.2.0.dev20250326.dist-info/RECORD +0 -118
  49. tests/__init__.py +0 -0
  50. tests/conftest.py +0 -67
  51. tests/test_backends.py +0 -1035
  52. tests/test_calibrating.py +0 -149
  53. tests/test_channels.py +0 -409
  54. tests/test_circuit.py +0 -1699
  55. tests/test_cloud.py +0 -219
  56. tests/test_compiler.py +0 -147
  57. tests/test_dmcircuit.py +0 -555
  58. tests/test_ensemble.py +0 -72
  59. tests/test_fgs.py +0 -310
  60. tests/test_gates.py +0 -156
  61. tests/test_interfaces.py +0 -562
  62. tests/test_keras.py +0 -160
  63. tests/test_miscs.py +0 -282
  64. tests/test_mpscircuit.py +0 -341
  65. tests/test_noisemodel.py +0 -156
  66. tests/test_qaoa.py +0 -86
  67. tests/test_qem.py +0 -152
  68. tests/test_quantum.py +0 -549
  69. tests/test_quantum_attr.py +0 -42
  70. tests/test_results.py +0 -380
  71. tests/test_shadows.py +0 -160
  72. tests/test_simplify.py +0 -46
  73. tests/test_stabilizer.py +0 -217
  74. tests/test_templates.py +0 -218
  75. tests/test_torchnn.py +0 -99
  76. tests/test_van.py +0 -102
  77. {tensorcircuit_nightly-1.2.0.dev20250326.dist-info → tensorcircuit_nightly-1.4.0.dev20251128.dist-info}/licenses/LICENSE +0 -0
tensorcircuit/fgs.py CHANGED
@@ -28,7 +28,6 @@ def onehot_matrix(i: int, j: int, N: int) -> Tensor:
28
28
 
29
29
  # TODO(@refraction-ray): efficiency benchmark with jit
30
30
  # TODO(@refraction-ray): FGS mixed state support?
31
- # TODO(@refraction-ray): overlap?
32
31
  # TODO(@refraction-ray): fermionic logarithmic negativity
33
32
 
34
33
 
@@ -73,17 +72,26 @@ class FGSSimulator:
73
72
  cmatrix: Optional[Tensor] = None,
74
73
  ):
75
74
  """
76
- _summary_
75
+ Initializes the Fermion Gaussian State (FGS) simulator.
77
76
 
78
- :param L: system size
77
+ The state can be initialized in one of four ways:
78
+ 1. By specifying the system size `L` and a list of `filled` sites, creating a product state.
79
+ 2. By providing a quadratic Hamiltonian `hc`, the ground state of which is used as the initial state.
80
+ 3. By directly providing the `alpha` matrix, which defines the Bogoliubov transformation.
81
+ 4. For debugging, by providing a pre-computed correlation matrix `cmatrix`.
82
+
83
+ :param L: The number of fermionic sites (system size).
79
84
  :type L: int
80
- :param filled: the fermion site that is fully occupied, defaults to None
85
+ :param filled: A list of site indices that are occupied by fermions in the initial state.
86
+ Defaults to None (no sites filled).
81
87
  :type filled: Optional[List[int]], optional
82
- :param alpha: directly specify the alpha tensor as the input
88
+ :param alpha: The matrix defining the Bogoliubov transformation from the vacuum state, of shape `(2L, L)`.
89
+ If provided, it directly specifies the initial state. Defaults to None.
83
90
  :type alpha: Optional[Tensor], optional
84
- :param hc: the input is given as the ground state of quadratic Hamiltonian ``hc``
91
+ :param hc: A quadratic Hamiltonian. The ground state of this Hamiltonian will be used as the initial state.
92
+ Defaults to None.
85
93
  :type hc: Optional[Tensor], optional
86
- :param cmatrix: only used for debug, defaults to None
94
+ :param cmatrix: A pre-computed correlation matrix, primarily for debugging purposes. Defaults to None.
87
95
  :type cmatrix: Optional[Tensor], optional
88
96
  """
89
97
  if filled is None:
@@ -105,6 +113,19 @@ class FGSSimulator:
105
113
  def fermion_diagonalization(
106
114
  cls, hc: Tensor, L: int
107
115
  ) -> Tuple[Tensor, Tensor, Tensor]:
116
+ """
117
+ Diagonalizes a quadratic fermionic Hamiltonian.
118
+
119
+ This method computes the eigenvalues, eigenvectors, and the alpha matrix for a given
120
+ quadratic Hamiltonian `hc`.
121
+
122
+ :param hc: The quadratic Hamiltonian to be diagonalized.
123
+ :type hc: Tensor
124
+ :param L: The number of fermionic sites.
125
+ :type L: int
126
+ :return: A tuple containing the eigenvalues, eigenvectors, and the alpha matrix.
127
+ :rtype: Tuple[Tensor, Tensor, Tensor]
128
+ """
108
129
  es, u = backend.eigh(hc)
109
130
  es = es[::-1]
110
131
  u = u[:, ::-1]
@@ -115,6 +136,19 @@ class FGSSimulator:
115
136
  def fermion_diagonalization_2(
116
137
  cls, hc: Tensor, L: int
117
138
  ) -> Tuple[Tensor, Tensor, Tensor]:
139
+ """
140
+ Alternative method for diagonalizing a quadratic fermionic Hamiltonian.
141
+
142
+ This method uses a different approach based on the Schur decomposition to diagonalize
143
+ the Hamiltonian.
144
+
145
+ :param hc: The quadratic Hamiltonian to be diagonalized.
146
+ :type hc: Tensor
147
+ :param L: The number of fermionic sites.
148
+ :type L: int
149
+ :return: A tuple containing the eigenvalues, eigenvectors, and the alpha matrix.
150
+ :rtype: Tuple[Tensor, Tensor, Tensor]
151
+ """
118
152
  w = cls.wmatrix(L)
119
153
  hm = 0.25 * w @ hc @ backend.adjoint(w)
120
154
  hm = backend.real((-1.0j) * hm)
@@ -140,6 +174,16 @@ class FGSSimulator:
140
174
 
141
175
  @staticmethod
142
176
  def wmatrix(L: int) -> Tensor:
177
+ """
178
+ Constructs the transformation matrix W.
179
+
180
+ This matrix transforms from the fermionic basis to the Majorana basis.
181
+
182
+ :param L: The number of fermionic sites.
183
+ :type L: int
184
+ :return: The transformation matrix W.
185
+ :rtype: Tensor
186
+ """
143
187
  w = np.zeros([2 * L, 2 * L], dtype=complex)
144
188
  for i in range(2 * L):
145
189
  if i % 2 == 1:
@@ -152,6 +196,16 @@ class FGSSimulator:
152
196
 
153
197
  @staticmethod
154
198
  def init_alpha(filled: List[int], L: int) -> Tensor:
199
+ """
200
+ Initializes the alpha matrix for a given set of filled sites.
201
+
202
+ :param filled: A list of site indices that are occupied by fermions.
203
+ :type filled: List[int]
204
+ :param L: The number of fermionic sites.
205
+ :type L: int
206
+ :return: The initialized alpha matrix.
207
+ :rtype: Tensor
208
+ """
155
209
  alpha = np.zeros([2 * L, L])
156
210
  for i in range(L):
157
211
  if i not in filled:
@@ -163,9 +217,29 @@ class FGSSimulator:
163
217
  return alpha
164
218
 
165
219
  def get_alpha(self) -> Tensor:
220
+ """
221
+ Returns the current alpha matrix of the FGS.
222
+
223
+ :return: The alpha matrix.
224
+ :rtype: Tensor
225
+ """
166
226
  return self.alpha
167
227
 
168
228
  def get_cmatrix(self, now_i: bool = True, now_j: bool = True) -> Tensor:
229
+ r"""
230
+ Calculates the correlation matrix.
231
+
232
+ The correlation matrix is defined as :math:`C_{ij} = \langle c_i^\dagger c_j \rangle`.
233
+ This method can also compute out-of-time-ordered correlators (OTOC) by specifying
234
+ whether to use the current or initial state for the `i` and `j` indices.
235
+
236
+ :param now_i: If True, use the current state for the `i` index. Defaults to True.
237
+ :type now_i: bool, optional
238
+ :param now_j: If True, use the current state for the `j` index. Defaults to True.
239
+ :type now_j: bool, optional
240
+ :return: The correlation matrix.
241
+ :rtype: Tensor
242
+ """
169
243
  # otoc in FGS language, see: https://arxiv.org/pdf/1908.03292.pdf
170
244
  # https://journals.aps.org/prb/pdf/10.1103/PhysRevB.99.054205
171
245
  # otoc for non=hermitian system is more subtle due to the undefined normalization
@@ -197,11 +271,11 @@ class FGSSimulator:
197
271
 
198
272
  def get_reduced_cmatrix(self, subsystems_to_trace_out: List[int]) -> Tensor:
199
273
  """
200
- get reduced correlation matrix by tracing out subsystems
274
+ Calculates the reduced correlation matrix by tracing out specified subsystems.
201
275
 
202
- :param subsystems_to_trace_out: list of sites to be traced out
276
+ :param subsystems_to_trace_out: A list of site indices to be traced out.
203
277
  :type subsystems_to_trace_out: List[int]
204
- :return: reduced density matrix
278
+ :return: The reduced correlation matrix.
205
279
  :rtype: Tensor
206
280
  """
207
281
  m = self.get_cmatrix()
@@ -222,20 +296,20 @@ class FGSSimulator:
222
296
 
223
297
  def renyi_entropy(self, n: int, subsystems_to_trace_out: List[int]) -> Tensor:
224
298
  """
225
- compute renyi_entropy of order ``n`` for the fermion state
299
+ Computes the Renyi entropy of order n for a given subsystem.
226
300
 
227
- :param n: _description_
301
+ :param n: The order of the Renyi entropy.
228
302
  :type n: int
229
- :param subsystems_to_trace_out: system sites to be traced out
303
+ :param subsystems_to_trace_out: A list of site indices to be traced out, defining the subsystem.
230
304
  :type subsystems_to_trace_out: List[int]
231
- :return: _description_
305
+ :return: The Renyi entropy of order n.
232
306
  :rtype: Tensor
233
307
  """
234
308
  m = self.get_reduced_cmatrix(subsystems_to_trace_out)
235
309
  lbd, _ = backend.eigh(m)
236
310
  lbd = backend.real(lbd)
237
311
  lbd = backend.relu(lbd)
238
- eps = 1e-6
312
+ eps = 1e-9
239
313
 
240
314
  entropy = backend.sum(backend.log(lbd**n + (1 - lbd) ** n + eps))
241
315
  s = 1 / (2 * (1 - n)) * entropy
@@ -248,15 +322,17 @@ class FGSSimulator:
248
322
  subsystems_to_trace_out: List[int],
249
323
  ) -> Tensor:
250
324
  """
325
+ Computes the charge moment of order n.
326
+
251
327
  Ref: https://arxiv.org/abs/2302.03330
252
328
 
253
- :param alpha: to be integrated
329
+ :param alpha: The alpha parameter for the charge moment calculation.
254
330
  :type alpha: Tensor
255
- :param n: n-order, Renyi-n
331
+ :param n: The order of the charge moment (Renyi-n).
256
332
  :type n: int
257
- :param subsystems_to_trace_out: _description_
333
+ :param subsystems_to_trace_out: A list of site indices to be traced out.
258
334
  :type subsystems_to_trace_out: List[int]
259
- :return: _description_
335
+ :return: The charge moment.
260
336
  :rtype: Tensor
261
337
  """
262
338
  m = self.get_reduced_cmatrix(subsystems_to_trace_out)
@@ -297,18 +373,23 @@ class FGSSimulator:
297
373
  with_std: bool = False,
298
374
  ) -> Tensor:
299
375
  """
376
+ Computes the Renyi entanglement asymmetry.
377
+
300
378
  Ref: https://arxiv.org/abs/2302.03330
301
379
 
302
- :param n: _description_
380
+ :param n: The order of the Renyi entanglement asymmetry.
303
381
  :type n: int
304
- :param subsystems_to_trace_out: _description_
382
+ :param subsystems_to_trace_out: A list of site indices to be traced out.
305
383
  :type subsystems_to_trace_out: List[int]
306
- :param batch: sample number, defaults 100
307
- :type batch: int
308
- :param status: random number for the sample, -pi to pi,
309
- with shape [batch, n]
310
- :type status: Optional[Tensor]
311
- :return: _description_
384
+ :param batch: The number of samples to use for the Monte Carlo estimation. Defaults to 100.
385
+ :type batch: int, optional
386
+ :param status: A tensor of random numbers for the sampling. If None, it will be generated internally.
387
+ Defaults to None.
388
+ :type status: Optional[Tensor], optional
389
+ :param with_std: If True, also return the standard deviation of the estimation. Defaults to False.
390
+ :type with_std: bool, optional
391
+ :return: The Renyi entanglement asymmetry.
392
+ If `with_std` is True, a tuple containing the asymmetry and its standard deviation is returned.
312
393
  :rtype: Tensor
313
394
  """
314
395
  r = []
@@ -354,11 +435,12 @@ class FGSSimulator:
354
435
 
355
436
  def entropy(self, subsystems_to_trace_out: Optional[List[int]] = None) -> Tensor:
356
437
  """
357
- compute von Neumann entropy for the fermion state
438
+ Computes the von Neumann entropy of a subsystem.
358
439
 
359
- :param subsystems_to_trace_out: _description_, defaults to None
440
+ :param subsystems_to_trace_out: A list of site indices to be traced out, defining the subsystem.
441
+ If None, the entropy of the entire system is computed. Defaults to None.
360
442
  :type subsystems_to_trace_out: Optional[List[int]], optional
361
- :return: _description_
443
+ :return: The von Neumann entropy.
362
444
  :rtype: Tensor
363
445
  """
364
446
  m = self.get_reduced_cmatrix(subsystems_to_trace_out) # type: ignore
@@ -366,7 +448,7 @@ class FGSSimulator:
366
448
  lbd = backend.real(lbd)
367
449
  lbd = backend.relu(lbd)
368
450
  # lbd /= backend.sum(lbd)
369
- eps = 1e-6
451
+ eps = 1e-9
370
452
  entropy = -backend.sum(
371
453
  lbd * backend.log(lbd + eps) + (1 - lbd) * backend.log(1 - lbd + eps)
372
454
  )
@@ -374,9 +456,11 @@ class FGSSimulator:
374
456
 
375
457
  def evol_hamiltonian(self, h: Tensor) -> None:
376
458
  r"""
377
- Evolve as :math:`e^{-i/2 \hat{h}}`
459
+ Evolves the state with a given Hamiltonian.
460
+
461
+ The evolution is given by :math:`e^{-i/2 \hat{h}}`.
378
462
 
379
- :param h: _description_
463
+ :param h: The Hamiltonian for the evolution.
380
464
  :type h: Tensor
381
465
  """
382
466
  # e^{-i/2 H}
@@ -387,9 +471,11 @@ class FGSSimulator:
387
471
 
388
472
  def evol_ihamiltonian(self, h: Tensor) -> None:
389
473
  r"""
390
- Evolve as :math:`e^{-1/2 \hat{h}}`
474
+ Evolves the state with a given Hamiltonian using imaginary time evolution.
391
475
 
392
- :param h: _description_
476
+ The evolution is given by :math:`e^{-1/2 \hat{h}}`.
477
+
478
+ :param h: The Hamiltonian for the evolution.
393
479
  :type h: Tensor
394
480
  """
395
481
  # e^{-1/2 H}
@@ -401,9 +487,11 @@ class FGSSimulator:
401
487
 
402
488
  def evol_ghamiltonian(self, h: Tensor) -> None:
403
489
  r"""
404
- Evolve as :math:`e^{-1/2 i \hat{h}}` with h generally non-Hermitian
490
+ Evolves the state with a general non-Hermitian Hamiltonian.
491
+
492
+ The evolution is given by :math:`e^{-1/2 i \hat{h}}`.
405
493
 
406
- :param h: _description_
494
+ :param h: The non-Hermitian Hamiltonian for the evolution.
407
495
  :type h: Tensor
408
496
  """
409
497
  # e^{-1/2 H}
@@ -414,11 +502,28 @@ class FGSSimulator:
414
502
  self.otcmatrix = {}
415
503
 
416
504
  def orthogonal(self) -> None:
505
+ """Orthogonalizes the alpha matrix using QR decomposition."""
417
506
  q, _ = backend.qr(self.alpha)
418
507
  self.alpha = q
419
508
 
420
509
  @staticmethod
421
510
  def hopping(chi: Tensor, i: int, j: int, L: int) -> Tensor:
511
+ r"""
512
+ Constructs the hopping Hamiltonian between two sites.
513
+
514
+ The hopping Hamiltonian is given by :math:`\chi c_i^\dagger c_j + h.c.`.
515
+
516
+ :param chi: The hopping strength.
517
+ :type chi: Tensor
518
+ :param i: The index of the first site.
519
+ :type i: int
520
+ :param j: The index of the second site.
521
+ :type j: int
522
+ :param L: The number of fermionic sites.
523
+ :type L: int
524
+ :return: The hopping Hamiltonian.
525
+ :rtype: Tensor
526
+ """
422
527
  # chi * ci dagger cj + hc.
423
528
  chi = backend.convert_to_tensor(chi)
424
529
  chi = backend.cast(chi, dtypestr)
@@ -429,19 +534,35 @@ class FGSSimulator:
429
534
 
430
535
  def evol_hp(self, i: int, j: int, chi: Tensor = 0) -> None:
431
536
  r"""
432
- The evolve Hamiltonian is :math:`\chi c_i^\dagger c_j +h.c.`
537
+ Evolves the state with a hopping Hamiltonian.
538
+
539
+ The evolution is governed by the Hamiltonian :math:`\chi c_i^\dagger c_j + h.c.`.
433
540
 
434
- :param i: _description_
541
+ :param i: The index of the first site.
435
542
  :type i: int
436
- :param j: _description_
543
+ :param j: The index of the second site.
437
544
  :type j: int
438
- :param chi: _description_, defaults to 0
545
+ :param chi: The hopping strength. Defaults to 0.
439
546
  :type chi: Tensor, optional
440
547
  """
441
548
  self.evol_hamiltonian(self.hopping(chi, i, j, self.L))
442
549
 
443
550
  @staticmethod
444
551
  def chemical_potential(chi: Tensor, i: int, L: int) -> Tensor:
552
+ r"""
553
+ Constructs the chemical potential Hamiltonian for a single site.
554
+
555
+ The chemical potential Hamiltonian is given by :math:`\chi c_i^\dagger c_i`.
556
+
557
+ :param chi: The chemical potential strength.
558
+ :type chi: Tensor
559
+ :param i: The index of the site.
560
+ :type i: int
561
+ :param L: The number of fermionic sites.
562
+ :type L: int
563
+ :return: The chemical potential Hamiltonian.
564
+ :rtype: Tensor
565
+ """
445
566
  chi = backend.convert_to_tensor(chi)
446
567
  chi = backend.cast(chi, dtypestr)
447
568
  m = chi / 2 * onehot_matrix(i, i, 2 * L)
@@ -450,6 +571,22 @@ class FGSSimulator:
450
571
 
451
572
  @staticmethod
452
573
  def sc_pairing(chi: Tensor, i: int, j: int, L: int) -> Tensor:
574
+ r"""
575
+ Constructs the superconducting pairing Hamiltonian between two sites.
576
+
577
+ The superconducting pairing Hamiltonian is given by :math:`\chi c_i^\dagger c_j^\dagger + h.c.`.
578
+
579
+ :param chi: The pairing strength.
580
+ :type chi: Tensor
581
+ :param i: The index of the first site.
582
+ :type i: int
583
+ :param j: The index of the second site.
584
+ :type j: int
585
+ :param L: The number of fermionic sites.
586
+ :type L: int
587
+ :return: The superconducting pairing Hamiltonian.
588
+ :rtype: Tensor
589
+ """
453
590
  chi = backend.convert_to_tensor(chi)
454
591
  chi = backend.cast(chi, dtypestr)
455
592
  m = chi / 2 * onehot_matrix(i, j + L, 2 * L)
@@ -459,41 +596,57 @@ class FGSSimulator:
459
596
 
460
597
  def evol_sp(self, i: int, j: int, chi: Tensor = 0) -> None:
461
598
  r"""
462
- The evolve Hamiltonian is :math:`chi c_i^\dagger c_j^\dagger +h.c.`
599
+ Evolves the state with a superconducting pairing Hamiltonian.
463
600
 
601
+ The evolution is governed by the Hamiltonian :math:`\chi c_i^\dagger c_j^\dagger + h.c.`.
464
602
 
465
- :param i: _description_
603
+ :param i: The index of the first site.
466
604
  :type i: int
467
- :param j: _description_
605
+ :param j: The index of the second site.
468
606
  :type j: int
469
- :param chi: _description_, defaults to 0
607
+ :param chi: The pairing strength. Defaults to 0.
470
608
  :type chi: Tensor, optional
471
609
  """
472
610
  self.evol_hamiltonian(self.sc_pairing(chi, i, j, self.L))
473
611
 
474
612
  def evol_cp(self, i: int, chi: Tensor = 0) -> None:
475
613
  r"""
476
- The evolve Hamiltonian is :math:`chi c_i^\dagger c_i`
614
+ Evolves the state with a chemical potential Hamiltonian.
615
+
616
+ The evolution is governed by the Hamiltonian :math:`\chi c_i^\dagger c_i`.
477
617
 
478
- :param i: _description_
618
+ :param i: The index of the site.
479
619
  :type i: int
480
- :param chi: _description_, defaults to 0
620
+ :param chi: The chemical potential strength. Defaults to 0.
481
621
  :type chi: Tensor, optional
482
622
  """
483
623
  self.evol_hamiltonian(self.chemical_potential(chi, i, self.L))
484
624
 
485
625
  def evol_icp(self, i: int, chi: Tensor = 0) -> None:
486
626
  r"""
487
- The evolve Hamiltonian is :math:`chi c_i^\dagger c_i` with :math:`\exp^{-H/2}`
627
+ Evolves the state with a chemical potential Hamiltonian using imaginary time evolution.
488
628
 
489
- :param i: _description_
629
+ The evolution is governed by :math:`e^{-H/2}` where :math:`H = \chi c_i^\dagger c_i`.
630
+
631
+ :param i: The index of the site.
490
632
  :type i: int
491
- :param chi: _description_, defaults to 0
633
+ :param chi: The chemical potential strength. Defaults to 0.
492
634
  :type chi: Tensor, optional
493
635
  """
494
636
  self.evol_ihamiltonian(self.chemical_potential(chi, i, self.L))
495
637
 
496
638
  def get_bogoliubov_uv(self) -> Tuple[Tensor, Tensor]:
639
+ r"""
640
+ Returns the u and v matrices of the Bogoliubov transformation.
641
+
642
+ The Bogoliubov transformation is defined as:
643
+ :math:`b_k = u_{k,i} a_i + v_{k,i} a_i^\dagger`
644
+
645
+ where :math:`b_k` are the new fermionic operators and :math:`a_i` are the original ones.
646
+
647
+ :return: A tuple containing the u and v matrices.
648
+ :rtype: Tuple[Tensor, Tensor]
649
+ """
497
650
  return (
498
651
  backend.gather1d(
499
652
  self.alpha, backend.convert_to_tensor([i for i in range(self.L)])
@@ -506,17 +659,27 @@ class FGSSimulator:
506
659
 
507
660
  def get_cmatrix_majorana(self) -> Tensor:
508
661
  r"""
509
- correlation matrix defined in majorana basis
510
- convention: :math:`gamma_0 = c_0 + c_0^\dagger`
511
- :math:`gamma_1 = i(c_0 - c_0^\dagger)`
662
+ Calculates the correlation matrix in the Majorana basis.
512
663
 
513
- :return: _description_
664
+ The Majorana operators are defined as:
665
+ :math:`\gamma_{2i} = c_i + c_i^\dagger`
666
+ :math:`\gamma_{2i+1} = -i(c_i - c_i^\dagger)`
667
+
668
+ :return: The correlation matrix in the Majorana basis.
514
669
  :rtype: Tensor
515
670
  """
516
671
  c = self.get_cmatrix()
517
672
  return self.wtransform @ c @ backend.adjoint(self.wtransform)
518
673
 
519
674
  def get_covariance_matrix(self) -> Tensor:
675
+ """
676
+ Calculates the covariance matrix.
677
+
678
+ The covariance matrix is defined from the Majorana correlation matrix.
679
+
680
+ :return: The covariance matrix.
681
+ :rtype: Tensor
682
+ """
520
683
  m = self.get_cmatrix_majorana()
521
684
  return -1.0j * (2 * m - backend.eye(self.L * 2))
522
685
 
@@ -524,34 +687,38 @@ class FGSSimulator:
524
687
  self, i: int, j: int, now_i: bool = True, now_j: bool = True
525
688
  ) -> Tensor:
526
689
  r"""
527
- expectation of two fermion terms
528
- convention: (c, c^\dagger)
529
- for i>L, c_{i-L}^\dagger is assumed
690
+ Calculates the expectation value of a two-fermion term.
691
+
692
+ The convention for the operators is (c, c^\dagger). For i >= L, the operator is c_{i-L}^\dagger.
530
693
 
531
- :param i: _description_
694
+ :param i: The index of the first fermion operator.
532
695
  :type i: int
533
- :param j: _description_
696
+ :param j: The index of the second fermion operator.
534
697
  :type j: int
535
- :return: _description_
698
+ :param now_i: Whether to use the current state for the first operator. Defaults to True.
699
+ :type now_i: bool, optional
700
+ :param now_j: Whether to use the current state for the second operator. Defaults to True.
701
+ :type now_j: bool, optional
702
+ :return: The expectation value of the two-fermion term.
536
703
  :rtype: Tensor
537
704
  """
538
705
  return self.get_cmatrix(now_i, now_j)[i][(j + self.L) % (2 * self.L)]
539
706
 
540
707
  def expectation_4body(self, i: int, j: int, k: int, l: int) -> Tensor:
541
708
  r"""
542
- expectation of four fermion terms using Wick Thm
543
- convention: (c, c^\dagger)
544
- for i>L, c_{i-L}^\dagger is assumed
709
+ Calculates the expectation value of a four-fermion term using Wick's theorem.
710
+
711
+ The convention for the operators is (c, c^\dagger). For an index m >= L, the operator is c_{m-L}^\dagger.
545
712
 
546
- :param i: _description_
713
+ :param i: The index of the first fermion operator.
547
714
  :type i: int
548
- :param j: _description_
715
+ :param j: The index of the second fermion operator.
549
716
  :type j: int
550
- :param k: _description_
717
+ :param k: The index of the third fermion operator.
551
718
  :type k: int
552
- :param l: _description_
719
+ :param l: The index of the fourth fermion operator.
553
720
  :type l: int
554
- :return: _description_
721
+ :return: The expectation value of the four-fermion term.
555
722
  :rtype: Tensor
556
723
  """
557
724
  e = (
@@ -563,12 +730,11 @@ class FGSSimulator:
563
730
 
564
731
  def post_select(self, i: int, keep: int = 1) -> None:
565
732
  """
566
- post select (project) the fermion state to occupation eigenstate
567
- <n_i> = ``keep``
733
+ Post-selects the state based on the occupation of a specific site.
568
734
 
569
- :param i: _description_
735
+ :param i: The index of the site to post-select on.
570
736
  :type i: int
571
- :param keep: _description_, defaults to 1
737
+ :param keep: The desired occupation number (0 or 1). Defaults to 1.
572
738
  :type keep: int, optional
573
739
  """
574
740
  # i is not jittable, keep is jittable
@@ -626,8 +792,23 @@ class FGSSimulator:
626
792
  alpha1 = alpha1 * mask02d + backend.tile(newcol[:, None], [1, self.L]) * mask12d
627
793
  q, _ = backend.qr(alpha1)
628
794
  self.alpha = q
795
+ self.cmatrix = None
629
796
 
630
797
  def cond_measure(self, ind: int, status: float, with_prob: bool = False) -> Tensor:
798
+ """
799
+ Performs a conditional measurement on a specific site.
800
+ The fermion Gaussian state is collapsed in the consistent way accordingly.
801
+
802
+ :param ind: The index of the site to measure.
803
+ :type ind: int
804
+ :param status: A random number between 0 and 1 to determine the measurement outcome.
805
+ :type status: float
806
+ :param with_prob: If True, also return the probabilities of the measurement outcomes. Defaults to False.
807
+ :type with_prob: bool, optional
808
+ :return: The measurement outcome (0 or 1). If `with_prob` is True,
809
+ a tuple containing the outcome and the probabilities is returned.
810
+ :rtype: Tensor
811
+ """
631
812
  p0 = backend.real(self.get_cmatrix()[ind, ind])
632
813
  prob = backend.convert_to_tensor([p0, 1 - p0])
633
814
  status = backend.convert_to_tensor(status)