tensorcircuit-nightly 1.2.1.dev20250725__py3-none-any.whl → 1.3.0.dev20250727__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.

tensorcircuit/fgs.py CHANGED
@@ -73,17 +73,26 @@ class FGSSimulator:
73
73
  cmatrix: Optional[Tensor] = None,
74
74
  ):
75
75
  """
76
- _summary_
76
+ Initializes the Fermion Gaussian State (FGS) simulator.
77
77
 
78
- :param L: system size
78
+ The state can be initialized in one of four ways:
79
+ 1. By specifying the system size `L` and a list of `filled` sites, creating a product state.
80
+ 2. By providing a quadratic Hamiltonian `hc`, the ground state of which is used as the initial state.
81
+ 3. By directly providing the `alpha` matrix, which defines the Bogoliubov transformation.
82
+ 4. For debugging, by providing a pre-computed correlation matrix `cmatrix`.
83
+
84
+ :param L: The number of fermionic sites (system size).
79
85
  :type L: int
80
- :param filled: the fermion site that is fully occupied, defaults to None
86
+ :param filled: A list of site indices that are occupied by fermions in the initial state.
87
+ Defaults to None (no sites filled).
81
88
  :type filled: Optional[List[int]], optional
82
- :param alpha: directly specify the alpha tensor as the input
89
+ :param alpha: The matrix defining the Bogoliubov transformation from the vacuum state, of shape `(2L, L)`.
90
+ If provided, it directly specifies the initial state. Defaults to None.
83
91
  :type alpha: Optional[Tensor], optional
84
- :param hc: the input is given as the ground state of quadratic Hamiltonian ``hc``
92
+ :param hc: A quadratic Hamiltonian. The ground state of this Hamiltonian will be used as the initial state.
93
+ Defaults to None.
85
94
  :type hc: Optional[Tensor], optional
86
- :param cmatrix: only used for debug, defaults to None
95
+ :param cmatrix: A pre-computed correlation matrix, primarily for debugging purposes. Defaults to None.
87
96
  :type cmatrix: Optional[Tensor], optional
88
97
  """
89
98
  if filled is None:
@@ -105,6 +114,19 @@ class FGSSimulator:
105
114
  def fermion_diagonalization(
106
115
  cls, hc: Tensor, L: int
107
116
  ) -> Tuple[Tensor, Tensor, Tensor]:
117
+ """
118
+ Diagonalizes a quadratic fermionic Hamiltonian.
119
+
120
+ This method computes the eigenvalues, eigenvectors, and the alpha matrix for a given
121
+ quadratic Hamiltonian `hc`.
122
+
123
+ :param hc: The quadratic Hamiltonian to be diagonalized.
124
+ :type hc: Tensor
125
+ :param L: The number of fermionic sites.
126
+ :type L: int
127
+ :return: A tuple containing the eigenvalues, eigenvectors, and the alpha matrix.
128
+ :rtype: Tuple[Tensor, Tensor, Tensor]
129
+ """
108
130
  es, u = backend.eigh(hc)
109
131
  es = es[::-1]
110
132
  u = u[:, ::-1]
@@ -115,6 +137,19 @@ class FGSSimulator:
115
137
  def fermion_diagonalization_2(
116
138
  cls, hc: Tensor, L: int
117
139
  ) -> Tuple[Tensor, Tensor, Tensor]:
140
+ """
141
+ Alternative method for diagonalizing a quadratic fermionic Hamiltonian.
142
+
143
+ This method uses a different approach based on the Schur decomposition to diagonalize
144
+ the Hamiltonian.
145
+
146
+ :param hc: The quadratic Hamiltonian to be diagonalized.
147
+ :type hc: Tensor
148
+ :param L: The number of fermionic sites.
149
+ :type L: int
150
+ :return: A tuple containing the eigenvalues, eigenvectors, and the alpha matrix.
151
+ :rtype: Tuple[Tensor, Tensor, Tensor]
152
+ """
118
153
  w = cls.wmatrix(L)
119
154
  hm = 0.25 * w @ hc @ backend.adjoint(w)
120
155
  hm = backend.real((-1.0j) * hm)
@@ -140,6 +175,16 @@ class FGSSimulator:
140
175
 
141
176
  @staticmethod
142
177
  def wmatrix(L: int) -> Tensor:
178
+ """
179
+ Constructs the transformation matrix W.
180
+
181
+ This matrix transforms from the fermionic basis to the Majorana basis.
182
+
183
+ :param L: The number of fermionic sites.
184
+ :type L: int
185
+ :return: The transformation matrix W.
186
+ :rtype: Tensor
187
+ """
143
188
  w = np.zeros([2 * L, 2 * L], dtype=complex)
144
189
  for i in range(2 * L):
145
190
  if i % 2 == 1:
@@ -152,6 +197,16 @@ class FGSSimulator:
152
197
 
153
198
  @staticmethod
154
199
  def init_alpha(filled: List[int], L: int) -> Tensor:
200
+ """
201
+ Initializes the alpha matrix for a given set of filled sites.
202
+
203
+ :param filled: A list of site indices that are occupied by fermions.
204
+ :type filled: List[int]
205
+ :param L: The number of fermionic sites.
206
+ :type L: int
207
+ :return: The initialized alpha matrix.
208
+ :rtype: Tensor
209
+ """
155
210
  alpha = np.zeros([2 * L, L])
156
211
  for i in range(L):
157
212
  if i not in filled:
@@ -163,9 +218,29 @@ class FGSSimulator:
163
218
  return alpha
164
219
 
165
220
  def get_alpha(self) -> Tensor:
221
+ """
222
+ Returns the current alpha matrix of the FGS.
223
+
224
+ :return: The alpha matrix.
225
+ :rtype: Tensor
226
+ """
166
227
  return self.alpha
167
228
 
168
229
  def get_cmatrix(self, now_i: bool = True, now_j: bool = True) -> Tensor:
230
+ """
231
+ Calculates the correlation matrix.
232
+
233
+ The correlation matrix is defined as :math:`C_{ij} = \langle c_i^\dagger c_j \rangle`.
234
+ This method can also compute out-of-time-ordered correlators (OTOC) by specifying
235
+ whether to use the current or initial state for the `i` and `j` indices.
236
+
237
+ :param now_i: If True, use the current state for the `i` index. Defaults to True.
238
+ :type now_i: bool, optional
239
+ :param now_j: If True, use the current state for the `j` index. Defaults to True.
240
+ :type now_j: bool, optional
241
+ :return: The correlation matrix.
242
+ :rtype: Tensor
243
+ """
169
244
  # otoc in FGS language, see: https://arxiv.org/pdf/1908.03292.pdf
170
245
  # https://journals.aps.org/prb/pdf/10.1103/PhysRevB.99.054205
171
246
  # otoc for non=hermitian system is more subtle due to the undefined normalization
@@ -197,11 +272,11 @@ class FGSSimulator:
197
272
 
198
273
  def get_reduced_cmatrix(self, subsystems_to_trace_out: List[int]) -> Tensor:
199
274
  """
200
- get reduced correlation matrix by tracing out subsystems
275
+ Calculates the reduced correlation matrix by tracing out specified subsystems.
201
276
 
202
- :param subsystems_to_trace_out: list of sites to be traced out
277
+ :param subsystems_to_trace_out: A list of site indices to be traced out.
203
278
  :type subsystems_to_trace_out: List[int]
204
- :return: reduced density matrix
279
+ :return: The reduced correlation matrix.
205
280
  :rtype: Tensor
206
281
  """
207
282
  m = self.get_cmatrix()
@@ -222,20 +297,20 @@ class FGSSimulator:
222
297
 
223
298
  def renyi_entropy(self, n: int, subsystems_to_trace_out: List[int]) -> Tensor:
224
299
  """
225
- compute renyi_entropy of order ``n`` for the fermion state
300
+ Computes the Renyi entropy of order n for a given subsystem.
226
301
 
227
- :param n: _description_
302
+ :param n: The order of the Renyi entropy.
228
303
  :type n: int
229
- :param subsystems_to_trace_out: system sites to be traced out
304
+ :param subsystems_to_trace_out: A list of site indices to be traced out, defining the subsystem.
230
305
  :type subsystems_to_trace_out: List[int]
231
- :return: _description_
306
+ :return: The Renyi entropy of order n.
232
307
  :rtype: Tensor
233
308
  """
234
309
  m = self.get_reduced_cmatrix(subsystems_to_trace_out)
235
310
  lbd, _ = backend.eigh(m)
236
311
  lbd = backend.real(lbd)
237
312
  lbd = backend.relu(lbd)
238
- eps = 1e-6
313
+ eps = 1e-9
239
314
 
240
315
  entropy = backend.sum(backend.log(lbd**n + (1 - lbd) ** n + eps))
241
316
  s = 1 / (2 * (1 - n)) * entropy
@@ -248,15 +323,17 @@ class FGSSimulator:
248
323
  subsystems_to_trace_out: List[int],
249
324
  ) -> Tensor:
250
325
  """
326
+ Computes the charge moment of order n.
327
+
251
328
  Ref: https://arxiv.org/abs/2302.03330
252
329
 
253
- :param alpha: to be integrated
330
+ :param alpha: The alpha parameter for the charge moment calculation.
254
331
  :type alpha: Tensor
255
- :param n: n-order, Renyi-n
332
+ :param n: The order of the charge moment (Renyi-n).
256
333
  :type n: int
257
- :param subsystems_to_trace_out: _description_
334
+ :param subsystems_to_trace_out: A list of site indices to be traced out.
258
335
  :type subsystems_to_trace_out: List[int]
259
- :return: _description_
336
+ :return: The charge moment.
260
337
  :rtype: Tensor
261
338
  """
262
339
  m = self.get_reduced_cmatrix(subsystems_to_trace_out)
@@ -297,18 +374,23 @@ class FGSSimulator:
297
374
  with_std: bool = False,
298
375
  ) -> Tensor:
299
376
  """
377
+ Computes the Renyi entanglement asymmetry.
378
+
300
379
  Ref: https://arxiv.org/abs/2302.03330
301
380
 
302
- :param n: _description_
381
+ :param n: The order of the Renyi entanglement asymmetry.
303
382
  :type n: int
304
- :param subsystems_to_trace_out: _description_
383
+ :param subsystems_to_trace_out: A list of site indices to be traced out.
305
384
  :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_
385
+ :param batch: The number of samples to use for the Monte Carlo estimation. Defaults to 100.
386
+ :type batch: int, optional
387
+ :param status: A tensor of random numbers for the sampling. If None, it will be generated internally.
388
+ Defaults to None.
389
+ :type status: Optional[Tensor], optional
390
+ :param with_std: If True, also return the standard deviation of the estimation. Defaults to False.
391
+ :type with_std: bool, optional
392
+ :return: The Renyi entanglement asymmetry.
393
+ If `with_std` is True, a tuple containing the asymmetry and its standard deviation is returned.
312
394
  :rtype: Tensor
313
395
  """
314
396
  r = []
@@ -354,11 +436,12 @@ class FGSSimulator:
354
436
 
355
437
  def entropy(self, subsystems_to_trace_out: Optional[List[int]] = None) -> Tensor:
356
438
  """
357
- compute von Neumann entropy for the fermion state
439
+ Computes the von Neumann entropy of a subsystem.
358
440
 
359
- :param subsystems_to_trace_out: _description_, defaults to None
441
+ :param subsystems_to_trace_out: A list of site indices to be traced out, defining the subsystem.
442
+ If None, the entropy of the entire system is computed. Defaults to None.
360
443
  :type subsystems_to_trace_out: Optional[List[int]], optional
361
- :return: _description_
444
+ :return: The von Neumann entropy.
362
445
  :rtype: Tensor
363
446
  """
364
447
  m = self.get_reduced_cmatrix(subsystems_to_trace_out) # type: ignore
@@ -366,7 +449,7 @@ class FGSSimulator:
366
449
  lbd = backend.real(lbd)
367
450
  lbd = backend.relu(lbd)
368
451
  # lbd /= backend.sum(lbd)
369
- eps = 1e-6
452
+ eps = 1e-9
370
453
  entropy = -backend.sum(
371
454
  lbd * backend.log(lbd + eps) + (1 - lbd) * backend.log(1 - lbd + eps)
372
455
  )
@@ -374,9 +457,11 @@ class FGSSimulator:
374
457
 
375
458
  def evol_hamiltonian(self, h: Tensor) -> None:
376
459
  r"""
377
- Evolve as :math:`e^{-i/2 \hat{h}}`
460
+ Evolves the state with a given Hamiltonian.
461
+
462
+ The evolution is given by :math:`e^{-i/2 \hat{h}}`.
378
463
 
379
- :param h: _description_
464
+ :param h: The Hamiltonian for the evolution.
380
465
  :type h: Tensor
381
466
  """
382
467
  # e^{-i/2 H}
@@ -387,9 +472,11 @@ class FGSSimulator:
387
472
 
388
473
  def evol_ihamiltonian(self, h: Tensor) -> None:
389
474
  r"""
390
- Evolve as :math:`e^{-1/2 \hat{h}}`
475
+ Evolves the state with a given Hamiltonian using imaginary time evolution.
391
476
 
392
- :param h: _description_
477
+ The evolution is given by :math:`e^{-1/2 \hat{h}}`.
478
+
479
+ :param h: The Hamiltonian for the evolution.
393
480
  :type h: Tensor
394
481
  """
395
482
  # e^{-1/2 H}
@@ -401,9 +488,11 @@ class FGSSimulator:
401
488
 
402
489
  def evol_ghamiltonian(self, h: Tensor) -> None:
403
490
  r"""
404
- Evolve as :math:`e^{-1/2 i \hat{h}}` with h generally non-Hermitian
491
+ Evolves the state with a general non-Hermitian Hamiltonian.
492
+
493
+ The evolution is given by :math:`e^{-1/2 i \hat{h}}`.
405
494
 
406
- :param h: _description_
495
+ :param h: The non-Hermitian Hamiltonian for the evolution.
407
496
  :type h: Tensor
408
497
  """
409
498
  # e^{-1/2 H}
@@ -414,11 +503,28 @@ class FGSSimulator:
414
503
  self.otcmatrix = {}
415
504
 
416
505
  def orthogonal(self) -> None:
506
+ """Orthogonalizes the alpha matrix using QR decomposition."""
417
507
  q, _ = backend.qr(self.alpha)
418
508
  self.alpha = q
419
509
 
420
510
  @staticmethod
421
511
  def hopping(chi: Tensor, i: int, j: int, L: int) -> Tensor:
512
+ """
513
+ Constructs the hopping Hamiltonian between two sites.
514
+
515
+ The hopping Hamiltonian is given by :math:`\chi c_i^\dagger c_j + h.c.`.
516
+
517
+ :param chi: The hopping strength.
518
+ :type chi: Tensor
519
+ :param i: The index of the first site.
520
+ :type i: int
521
+ :param j: The index of the second site.
522
+ :type j: int
523
+ :param L: The number of fermionic sites.
524
+ :type L: int
525
+ :return: The hopping Hamiltonian.
526
+ :rtype: Tensor
527
+ """
422
528
  # chi * ci dagger cj + hc.
423
529
  chi = backend.convert_to_tensor(chi)
424
530
  chi = backend.cast(chi, dtypestr)
@@ -429,19 +535,35 @@ class FGSSimulator:
429
535
 
430
536
  def evol_hp(self, i: int, j: int, chi: Tensor = 0) -> None:
431
537
  r"""
432
- The evolve Hamiltonian is :math:`\chi c_i^\dagger c_j +h.c.`
538
+ Evolves the state with a hopping Hamiltonian.
539
+
540
+ The evolution is governed by the Hamiltonian :math:`\chi c_i^\dagger c_j + h.c.`.
433
541
 
434
- :param i: _description_
542
+ :param i: The index of the first site.
435
543
  :type i: int
436
- :param j: _description_
544
+ :param j: The index of the second site.
437
545
  :type j: int
438
- :param chi: _description_, defaults to 0
546
+ :param chi: The hopping strength. Defaults to 0.
439
547
  :type chi: Tensor, optional
440
548
  """
441
549
  self.evol_hamiltonian(self.hopping(chi, i, j, self.L))
442
550
 
443
551
  @staticmethod
444
552
  def chemical_potential(chi: Tensor, i: int, L: int) -> Tensor:
553
+ """
554
+ Constructs the chemical potential Hamiltonian for a single site.
555
+
556
+ The chemical potential Hamiltonian is given by :math:`\chi c_i^\dagger c_i`.
557
+
558
+ :param chi: The chemical potential strength.
559
+ :type chi: Tensor
560
+ :param i: The index of the site.
561
+ :type i: int
562
+ :param L: The number of fermionic sites.
563
+ :type L: int
564
+ :return: The chemical potential Hamiltonian.
565
+ :rtype: Tensor
566
+ """
445
567
  chi = backend.convert_to_tensor(chi)
446
568
  chi = backend.cast(chi, dtypestr)
447
569
  m = chi / 2 * onehot_matrix(i, i, 2 * L)
@@ -450,6 +572,22 @@ class FGSSimulator:
450
572
 
451
573
  @staticmethod
452
574
  def sc_pairing(chi: Tensor, i: int, j: int, L: int) -> Tensor:
575
+ """
576
+ Constructs the superconducting pairing Hamiltonian between two sites.
577
+
578
+ The superconducting pairing Hamiltonian is given by :math:`\chi c_i^\dagger c_j^\dagger + h.c.`.
579
+
580
+ :param chi: The pairing strength.
581
+ :type chi: Tensor
582
+ :param i: The index of the first site.
583
+ :type i: int
584
+ :param j: The index of the second site.
585
+ :type j: int
586
+ :param L: The number of fermionic sites.
587
+ :type L: int
588
+ :return: The superconducting pairing Hamiltonian.
589
+ :rtype: Tensor
590
+ """
453
591
  chi = backend.convert_to_tensor(chi)
454
592
  chi = backend.cast(chi, dtypestr)
455
593
  m = chi / 2 * onehot_matrix(i, j + L, 2 * L)
@@ -459,41 +597,57 @@ class FGSSimulator:
459
597
 
460
598
  def evol_sp(self, i: int, j: int, chi: Tensor = 0) -> None:
461
599
  r"""
462
- The evolve Hamiltonian is :math:`chi c_i^\dagger c_j^\dagger +h.c.`
600
+ Evolves the state with a superconducting pairing Hamiltonian.
463
601
 
602
+ The evolution is governed by the Hamiltonian :math:`\chi c_i^\dagger c_j^\dagger + h.c.`.
464
603
 
465
- :param i: _description_
604
+ :param i: The index of the first site.
466
605
  :type i: int
467
- :param j: _description_
606
+ :param j: The index of the second site.
468
607
  :type j: int
469
- :param chi: _description_, defaults to 0
608
+ :param chi: The pairing strength. Defaults to 0.
470
609
  :type chi: Tensor, optional
471
610
  """
472
611
  self.evol_hamiltonian(self.sc_pairing(chi, i, j, self.L))
473
612
 
474
613
  def evol_cp(self, i: int, chi: Tensor = 0) -> None:
475
614
  r"""
476
- The evolve Hamiltonian is :math:`chi c_i^\dagger c_i`
615
+ Evolves the state with a chemical potential Hamiltonian.
616
+
617
+ The evolution is governed by the Hamiltonian :math:`\chi c_i^\dagger c_i`.
477
618
 
478
- :param i: _description_
619
+ :param i: The index of the site.
479
620
  :type i: int
480
- :param chi: _description_, defaults to 0
621
+ :param chi: The chemical potential strength. Defaults to 0.
481
622
  :type chi: Tensor, optional
482
623
  """
483
624
  self.evol_hamiltonian(self.chemical_potential(chi, i, self.L))
484
625
 
485
626
  def evol_icp(self, i: int, chi: Tensor = 0) -> None:
486
627
  r"""
487
- The evolve Hamiltonian is :math:`chi c_i^\dagger c_i` with :math:`\exp^{-H/2}`
628
+ Evolves the state with a chemical potential Hamiltonian using imaginary time evolution.
488
629
 
489
- :param i: _description_
630
+ The evolution is governed by :math:`e^{-H/2}` where :math:`H = \chi c_i^\dagger c_i`.
631
+
632
+ :param i: The index of the site.
490
633
  :type i: int
491
- :param chi: _description_, defaults to 0
634
+ :param chi: The chemical potential strength. Defaults to 0.
492
635
  :type chi: Tensor, optional
493
636
  """
494
637
  self.evol_ihamiltonian(self.chemical_potential(chi, i, self.L))
495
638
 
496
639
  def get_bogoliubov_uv(self) -> Tuple[Tensor, Tensor]:
640
+ """
641
+ Returns the u and v matrices of the Bogoliubov transformation.
642
+
643
+ The Bogoliubov transformation is defined as:
644
+ :math:`b_k = u_{k,i} a_i + v_{k,i} a_i^\dagger`
645
+
646
+ where :math:`b_k` are the new fermionic operators and :math:`a_i` are the original ones.
647
+
648
+ :return: A tuple containing the u and v matrices.
649
+ :rtype: Tuple[Tensor, Tensor]
650
+ """
497
651
  return (
498
652
  backend.gather1d(
499
653
  self.alpha, backend.convert_to_tensor([i for i in range(self.L)])
@@ -506,17 +660,27 @@ class FGSSimulator:
506
660
 
507
661
  def get_cmatrix_majorana(self) -> Tensor:
508
662
  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)`
663
+ Calculates the correlation matrix in the Majorana basis.
512
664
 
513
- :return: _description_
665
+ The Majorana operators are defined as:
666
+ :math:`\gamma_{2i} = c_i + c_i^\dagger`
667
+ :math:`\gamma_{2i+1} = -i(c_i - c_i^\dagger)`
668
+
669
+ :return: The correlation matrix in the Majorana basis.
514
670
  :rtype: Tensor
515
671
  """
516
672
  c = self.get_cmatrix()
517
673
  return self.wtransform @ c @ backend.adjoint(self.wtransform)
518
674
 
519
675
  def get_covariance_matrix(self) -> Tensor:
676
+ """
677
+ Calculates the covariance matrix.
678
+
679
+ The covariance matrix is defined from the Majorana correlation matrix.
680
+
681
+ :return: The covariance matrix.
682
+ :rtype: Tensor
683
+ """
520
684
  m = self.get_cmatrix_majorana()
521
685
  return -1.0j * (2 * m - backend.eye(self.L * 2))
522
686
 
@@ -524,34 +688,38 @@ class FGSSimulator:
524
688
  self, i: int, j: int, now_i: bool = True, now_j: bool = True
525
689
  ) -> Tensor:
526
690
  r"""
527
- expectation of two fermion terms
528
- convention: (c, c^\dagger)
529
- for i>L, c_{i-L}^\dagger is assumed
691
+ Calculates the expectation value of a two-fermion term.
692
+
693
+ The convention for the operators is (c, c^\dagger). For i >= L, the operator is c_{i-L}^\dagger.
530
694
 
531
- :param i: _description_
695
+ :param i: The index of the first fermion operator.
532
696
  :type i: int
533
- :param j: _description_
697
+ :param j: The index of the second fermion operator.
534
698
  :type j: int
535
- :return: _description_
699
+ :param now_i: Whether to use the current state for the first operator. Defaults to True.
700
+ :type now_i: bool, optional
701
+ :param now_j: Whether to use the current state for the second operator. Defaults to True.
702
+ :type now_j: bool, optional
703
+ :return: The expectation value of the two-fermion term.
536
704
  :rtype: Tensor
537
705
  """
538
706
  return self.get_cmatrix(now_i, now_j)[i][(j + self.L) % (2 * self.L)]
539
707
 
540
708
  def expectation_4body(self, i: int, j: int, k: int, l: int) -> Tensor:
541
709
  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
710
+ Calculates the expectation value of a four-fermion term using Wick's theorem.
711
+
712
+ The convention for the operators is (c, c^\dagger). For an index m >= L, the operator is c_{m-L}^\dagger.
545
713
 
546
- :param i: _description_
714
+ :param i: The index of the first fermion operator.
547
715
  :type i: int
548
- :param j: _description_
716
+ :param j: The index of the second fermion operator.
549
717
  :type j: int
550
- :param k: _description_
718
+ :param k: The index of the third fermion operator.
551
719
  :type k: int
552
- :param l: _description_
720
+ :param l: The index of the fourth fermion operator.
553
721
  :type l: int
554
- :return: _description_
722
+ :return: The expectation value of the four-fermion term.
555
723
  :rtype: Tensor
556
724
  """
557
725
  e = (
@@ -563,12 +731,11 @@ class FGSSimulator:
563
731
 
564
732
  def post_select(self, i: int, keep: int = 1) -> None:
565
733
  """
566
- post select (project) the fermion state to occupation eigenstate
567
- <n_i> = ``keep``
734
+ Post-selects the state based on the occupation of a specific site.
568
735
 
569
- :param i: _description_
736
+ :param i: The index of the site to post-select on.
570
737
  :type i: int
571
- :param keep: _description_, defaults to 1
738
+ :param keep: The desired occupation number (0 or 1). Defaults to 1.
572
739
  :type keep: int, optional
573
740
  """
574
741
  # i is not jittable, keep is jittable
@@ -626,8 +793,23 @@ class FGSSimulator:
626
793
  alpha1 = alpha1 * mask02d + backend.tile(newcol[:, None], [1, self.L]) * mask12d
627
794
  q, _ = backend.qr(alpha1)
628
795
  self.alpha = q
796
+ self.cmatrix = None
629
797
 
630
798
  def cond_measure(self, ind: int, status: float, with_prob: bool = False) -> Tensor:
799
+ """
800
+ Performs a conditional measurement on a specific site.
801
+ The fermion Gaussian state is collapsed in the consistent way accordingly.
802
+
803
+ :param ind: The index of the site to measure.
804
+ :type ind: int
805
+ :param status: A random number between 0 and 1 to determine the measurement outcome.
806
+ :type status: float
807
+ :param with_prob: If True, also return the probabilities of the measurement outcomes. Defaults to False.
808
+ :type with_prob: bool, optional
809
+ :return: The measurement outcome (0 or 1). If `with_prob` is True,
810
+ a tuple containing the outcome and the probabilities is returned.
811
+ :rtype: Tensor
812
+ """
631
813
  p0 = backend.real(self.get_cmatrix()[ind, ind])
632
814
  prob = backend.convert_to_tensor([p0, 1 - p0])
633
815
  status = backend.convert_to_tensor(status)
@@ -260,6 +260,17 @@ class MPSCircuit(AbstractCircuit):
260
260
  index_to: int,
261
261
  split: Optional[Dict[str, Any]] = None,
262
262
  ) -> None:
263
+ """
264
+ Apply a series of SWAP gates to move a qubit from ``index_from`` to ``index_to``.
265
+
266
+ :param index_from: The starting index of the qubit.
267
+ :type index_from: int
268
+ :param index_to: The destination index of the qubit.
269
+ :type index_to: int
270
+ :param split: Truncation options for the SWAP gates. Defaults to None.
271
+ consistent with the split option of the class.
272
+ :type split: Optional[Dict[str, Any]], optional
273
+ """
263
274
  if split is None:
264
275
  split = self.split
265
276
  self.position(index_from)
@@ -437,7 +448,15 @@ class MPSCircuit(AbstractCircuit):
437
448
  split: Optional[Dict[str, Any]] = None,
438
449
  ) -> None:
439
450
  """
440
- Reduce the bond dimension between two adjacent sites by SVD
451
+ Reduce the bond dimension between two adjacent sites using SVD.
452
+
453
+ :param index_left: The index of the left tensor of the bond to be truncated.
454
+ :type index_left: int
455
+ :param center_left: If True, the orthogonality center will be on the left tensor after truncation.
456
+ Otherwise, it will be on the right tensor. Defaults to True.
457
+ :type center_left: bool, optional
458
+ :param split: Truncation options for the SVD. Defaults to None.
459
+ :type split: Optional[Dict[str, Any]], optional
441
460
  """
442
461
  if split is None:
443
462
  split = self.split
@@ -463,7 +482,22 @@ class MPSCircuit(AbstractCircuit):
463
482
  split: Optional[Dict[str, Any]] = None,
464
483
  ) -> None:
465
484
  """
466
- Apply a MPO to the MPS
485
+ Apply a Matrix Product Operator (MPO) to the MPS.
486
+
487
+ The application involves three main steps:
488
+ 1. Contract the MPO tensors with the corresponding MPS tensors.
489
+ 2. Canonicalize the resulting tensors by moving the orthogonality center.
490
+ 3. Truncate the bond dimensions to control complexity.
491
+
492
+ :param tensors: A sequence of tensors representing the MPO.
493
+ :type tensors: Sequence[Tensor]
494
+ :param index_left: The starting index on the MPS where the MPO is applied.
495
+ :type index_left: int
496
+ :param center_left: If True, the final orthogonality center will be at the left end of the MPO.
497
+ Otherwise, it will be at the right end. Defaults to True.
498
+ :type center_left: bool, optional
499
+ :param split: Truncation options for bond dimension reduction. Defaults to None.
500
+ :type split: Optional[Dict[str, Any]], optional
467
501
  """
468
502
  # step 1:
469
503
  # contract tensor
@@ -521,10 +555,17 @@ class MPSCircuit(AbstractCircuit):
521
555
  *index: int,
522
556
  split: Optional[Dict[str, Any]] = None,
523
557
  ) -> None:
524
- # TODO(@SUSYUSTC): jax autograd is wrong on this function
525
558
  """
526
- Apply a n-qubit gate by transforming the gate to MPO
559
+ Apply an n-qubit gate to the MPS by converting it to an MPO.
560
+
561
+ :param gate: The n-qubit gate to apply.
562
+ :type gate: Gate
563
+ :param index: The indices of the qubits to apply the gate to.
564
+ :type index: int
565
+ :param split: Truncation options for the MPO application. Defaults to None.
566
+ :type split: Optional[Dict[str, Any]], optional
527
567
  """
568
+ # TODO(@SUSYUSTC): jax autograd is wrong on this function
528
569
  ordered = np.all(np.diff(index) > 0)
529
570
  if not ordered:
530
571
  order = np.argsort(index)