Sari la conținutul principal
Acest proiect este în versiune beta. Ai găsit o eroare? Deschide un issue pe GitHub. Ai o întrebare sau o idee? Întreabă în Discussions — ne-ar plăcea să aflăm părerea ta!
Cum este calitatea traducerii pe această pagină?

Grupează termenii operatorului: folosește structura operatorului

Gruparea este una dintre operațiile din qiskit_fermions.operators.terms, care reunește rutine ce partiționează termenii unui operator pe baza structurii lor.

Așa cum este descris în ghidul operatorilor, operatorii pot stoca un tablou de grupuri, o parte opțională a structurii de date rare care asociază fiecărui termen un indice de grup. Termenii care au același indice de grup formează un grup. Acest lucru îți permite să folosești sistematic structura în procesarea ulterioară.

Prin gruparea termenilor înrudiți (fie după proprietăți fizice, relații algebrice sau simetrii specifice problemei), poți obține mai multe beneficii:

  • Sinteză optimizată a circuitelor: termenii grupați transportă informații specifice problemei prin stivă, permițând o optimizare mai simplă a circuitelor sintetizate. Rezultatul este o adâncime a circuitului și un număr de porți reduse.

  • Păstrarea structurii fizice: grupurile codifică structură semnificativă din problema inițială (de exemplu, tipare de interacțiune sau simetrii) care poate fi folosită pentru descompuneri mai semnificative din punct de vedere fizic.

  • Selectarea seturilor de flux: gruparea poate codifica în mod natural seturi de flux și alte structuri din teoria grafurilor relevante pentru simularea cuantică, așa cum se arată în [1].

  • Stabilitate algoritmică îmbunătățită: așa cum se demonstrează în rutina SqDRIFT, unii algoritmi pot beneficia de stabilitate sau performanță îmbunătățite datorită păstrării proprietăților fizice.

  • Factori ai formulei de produs: o formulă de produs fermionică împarte un operator în grupurile sale, astfel încât gruparea determină atât costul, cât și eroarea Trotter a unei evoluții în timp. Vezi Sintetizarea unei porți Evolution în spațiul fermionic.

Utilizare​

Cea mai simplă modalitate de a defini o grupare a operatorului este setarea atributului groups al operatorului țintă. Mai jos este un exemplu de grupare a termenilor după seturile de flux pe linii, așa cum se arată în Figura 1c din [1].

Sfat

The qiskit_fermions.operators.terms.grouping module provides convenience methods for automatically identifying structure in an operator and assigning group indices accordingly.

>>> import rustworkx as rx
>>> graph = rx.PyDiGraph()
>>> _ = graph.add_nodes_from(range(6))
>>> edges = [(0, 1), (1, 2), (3, 0), (1, 4), (5, 2), (5, 4), (4, 3)]
>>> groups = [0, 0, 1, 2, 1, 3, 3]
>>> edges_with_group_as_payload = [(i, j, g) for (i, j), g in zip(edges, groups)]
>>> _ = graph.add_edges_from(edges_with_group_as_payload)
>>> from rustworkx.visualization import mpl_draw
>>> mpl_draw(
... graph,
... pos={i: (i % 3, i // 3) for i in range(6)},
... edge_labels=str,
... with_labels=True,
... )
<Figure size ... with 1 Axes>

A simple directed graph on which to define a MajoranaOperator.

Aceasta este o rețea simplă de două pe trei de moduri Majorana conectate prin muchii orientate. Fiecare muchie reprezintă un termen al operatorului care acționează asupra celor două moduri conectate. Scopul este să grupăm acești termeni după etichetele muchiilor (afișate pe graf). Termenii conectați prin muchii cu aceeași etichetă sunt plasați în același grup. Codul următor arată cum se poate face acest lucru:

>>> from qiskit_fermions.operators import MajoranaOperator
>>>
>>> # Construct operator directly using sparse arrays
>>> # 7 terms, each with coefficient 1.0, modes from edge endpoints
>>> op = MajoranaOperator(
... coeffs=[1.0] * 7,
... modes=[node for edge in edges for node in edge],
... boundaries=[0, 2, 4, 6, 8, 10, 12, 14],
... )
>>>
>>> # Assign group indices to terms (groups is part of the sparse data structure)
>>> op.groups = groups
>>>
>>> # Partition operator by groups
>>> grouped_ops = op.split_out_groups()
>>>
>>> # Inspect each group
>>> for i, g in enumerate(grouped_ops):
... print(f"Group {i}: {list(sorted(g.iter_terms()))}")
Group 0: [([0, 1], (1+0j)), ([1, 2], (1+0j))]
Group 1: [([3, 0], (1+0j)), ([5, 2], (1+0j))]
Group 2: [([1, 4], (1+0j))]
Group 3: [([4, 3], (1+0j)), ([5, 4], (1+0j))]

Analizează o grupare​

Grupurile nu prescriu nicio semnificație proprie: tabloul de grupuri înregistrează care termeni aparțin împreună, niciodată de ce. Nicio rutină din această bibliotecă nu raportează dacă o grupare este „corectă”, deoarece nu există o noțiune unică de corectitudine față de care să se raporteze. Consumatorii din aval presupun totuși anumite proprietăți ale unei grupări, iar funcțiile din această secțiune îți permit să verifici o astfel de presupunere dinainte, în loc să plătești pentru ea la fiecare apel.

Cea mai comună convenție este ca fiecare grup să fie hermitian separat. Aceasta este ceea ce face posibile formulele de produs fermionice aleatorizate: un singur ap†aqa^\dagger_p a_q cu p≠qp \neq q nu este hermitian, deci evoluția sa în timp nu este unitară și nu poate fi eșantionată de unul singur. Asocierea lui cu aq†apa^\dagger_q a_p produce un grup care poate fi eșantionat.

>>> from qiskit_fermions.operators import FermionOperator
>>> from qiskit_fermions.operators.terms.grouping import (
... group_coeff_means,
... groups_are_hermitian,
... groups_have_uniform_coeffs,
... )
>>>
>>> # a conjugate pair, plus one unpaired term. The operator is built from the sparse
>>> # arrays rather than from a dictionary, because only the former fixes the term order
>>> # that the group indices below are paired with.
>>> pair_and_single = FermionOperator(
... [1.0, 1.0, 1.0],
... [True, False, True, False, True, False],
... [0, 1, 1, 0, 2, 3],
... [0, 2, 4, 6],
... )
>>> pair_and_single.groups = [0, 0, 1]
>>>
>>> groups_are_hermitian(pair_and_single) # group 1 is unpaired
[True, False]
>>> group_coeff_means(pair_and_single)
[1.0, 1.0]

Un singur indice de grup pe termen este impus​

Tabloul de grupuri conține un indice pe termen, iar atribuirea unuia de altă lungime generează o eroare. Nimic din aval nu reverifică această invariantă, așa că ea este impusă acolo unde indicii intră în operator: un tablou prea scurt ar elimina în tăcere termenii finali, iar unul prea lung ar inventa grupuri pe care niciun termen nu le conține.

>>> pair_and_single.groups = [0, 0] # one index short, on a three-term operator
Traceback (most recent call last):
ValueError: expected one group index per term, but got 2 for 3 terms

Ștergerea indicilor de grup prin atribuirea lui None este întotdeauna permisă.

Cele două verificări sunt independente​

groups_have_uniform_coeffs() raportează dacă coeficienții unui grup coincid, aceasta fiind presupunerea pe care o face group_coeff_means() când face media magnitudinilor. Nu este o formă mai slabă a verificării hermiticității: niciuna dintre verificări nu o implică pe cealaltă, în niciun sens.

>>> from qiskit_fermions.operators.terms.grouping import (
... groups_are_hermitian,
... groups_have_uniform_coeffs,
... )
>>> # uniform coefficients, but not Hermitian: the terms are not each other's adjoint
>>> uniform = FermionOperator(
... [1.0, 1.0],
... [True, False, True, False],
... [0, 1, 2, 3],
... [0, 2, 4],
... )
>>> uniform.groups = [0, 0]
>>> groups_have_uniform_coeffs(uniform), groups_are_hermitian(uniform)
([True], [False])
>>> # Hermitian, but with mixed magnitudes: two conjugate pairs at different scales
>>> mixed = FermionOperator(
... [1.0, 1.0, 5.0, 5.0],
... [True, False, True, False, True, False, True, False],
... [0, 1, 1, 0, 2, 3, 3, 2],
... [0, 2, 4, 6, 8],
... )
>>> mixed.groups = [0, 0, 0, 0]
>>> groups_are_hermitian(mixed), groups_have_uniform_coeffs(mixed)
([True], [False])

În mod implicit se compară magnitudinile, deoarece aceasta este ceea ce mediază group_coeff_means(). O pereche conjugată hermitian cu coeficienți complecși are magnitudini egale, dar coeficienți diferiți, deci satisface doar forma implicită.

>>> conjugate = FermionOperator(
... [1.0j, -1.0j],
... [True, False, True, False],
... [0, 1, 1, 0],
... [0, 2, 4],
... )
>>> conjugate.groups = [0, 0]
>>> groups_have_uniform_coeffs(conjugate)
[True]
>>> groups_have_uniform_coeffs(conjugate, abs=False)
[False]
Notă

groups_are_hermitian() moștenește garanția unilaterală a lui is_hermitian(): o intrare True este întotdeauna de încredere, în timp ce o intrare False este de încredere doar pentru tipurile de operatori a căror formă normală este o autentică formă canonică. Consultă tipul specific de operator pentru a afla care caz se aplică.

[1] (1,2)

A. Gandon et al., Stabilizer-based quantum simulation of fermion dynamics with local qubit encodings, arXiv:2512.11418v2.