Lumaktaw sa pangunahing nilalaman
Ang proyektong ito ay nasa beta. Nakakita ng bug? Mag-bukas ng GitHub issue. May tanong o ideya? Magtanong sa Discussions — gusto naming marinig ang iyong feedback!
Gaano kaganda ang kalidad ng pagsasalin sa pahinang ito?

Pagpapangkat ng mga operator term: gamitin ang istruktura ng operator

Ang pagpapangkat ay isa sa mga operasyon sa ilalim ng qiskit_fermions.operators.terms, na nagtitipon ng mga routine na nagpa-partition ng mga term ng operator batay sa istruktura ng mga ito.

Gaya ng inilarawan sa gabay sa mga operator, maaaring mag-imbak ang mga operator ng groups array, isang opsyonal na bahagi ng sparse data structure na nag-uugnay ng bawat term sa isang group index. Ang mga term na may parehong group index ay bumubuo ng isang group. Pinapayagan ka nitong sistematikong magamit ang istruktura sa downstream na pagpoproseso.

Sa pamamagitan ng pagpapangkat ng mga magkakaugnay na term (batay man sa pisikal na katangian, algebraic na ugnayan, o simetriyang partikular sa problema), makakakuha ka ng ilang benepisyo:

  • Optimized na circuit synthesis: Dinadala ng mga pinangkat na term ang impormasyong partikular sa problema sa buong stack, kaya mas madali ang pag-optimize ng mga na-synthesize na circuit. Nagreresulta ito sa mas mababang circuit depth at bilang ng gate.

  • Pagpepreserba ng pisikal na istruktura: Ine-encode ng mga group ang makabuluhang istruktura mula sa orihinal na problema (halimbawa, mga pattern ng interaksyon o simetriya) na magagamit para sa mas makabuluhang pisikal na mga decomposition.

  • Pagpili ng flow set: Natural na maisasa-code ng pagpapangkat ang mga flow set at iba pang graph-theoretic na istruktura na may kaugnayan sa quantum simulation, gaya ng ipinakita sa [1].

  • Mas pinahusay na algorithmic stability: Gaya ng ipinakita sa SqDRIFT routine, may ilang algorithm na makikinabang sa mas pinahusay na stability o performance dahil sa pagpepreserba ng mga pisikal na katangian.

  • Mga product-formula factor: Hinahati ng fermionic product formula ang isang operator sa mga group nito, kaya ang pagpapangkat ang nagtatakda ng parehong gastos at ng Trotter error ng isang time evolution. Tingnan ang Mag-synthesize ng Evolution gate sa fermionic space.

Paggamit​

Ang pinakasimpleng paraan para mag-define ng operator grouping ay ang pagtatakda ng groups attribute ng target na operator. Nasa ibaba ang halimbawa ng pagpapangkat ng mga term ayon sa line flow sets gaya ng ipinakita sa Figure 1c ng [1].

Hint

Nagbibigay ang module na qiskit_fermions.operators.terms.grouping ng mga convenience method para awtomatikong tukuyin ang istruktura sa isang operator at magtakda ng mga group index nang naaayon.

>>> 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.

Ito ay isang simpleng two-by-three na lattice ng mga Majorana mode na konektado ng mga directed edge. Ang bawat edge ay kumakatawan sa isang term sa operator na kumikilos sa dalawang konektadong mode. Ang layunin ay pangkatin ang mga term na ito ayon sa mga label ng edge ng mga ito (ipinapakita sa graph). Ang mga term na konektado ng mga edge na may parehong label ay inilalagay sa iisang group. Ipinapakita ng sumusunod na code kung paano ito magagawa:

>>> 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))]

Pag-aralan ang isang grouping​

Walang sariling kahulugan ang mga group: itinatala ng groups array kung aling mga term ang magkakasama, pero hindi kailanman kung bakit. Walang routine sa library na ito ang nag-uulat kung "tama" ang isang grouping, dahil walang iisang kahulugan ng kawastuhan na pagbabatayan. Gayunpaman, ang mga downstream na consumer ay may mga ipinapalagay na katangian ng isang grouping, at hinahayaan ka ng mga function sa seksyong ito na suriin ang ganoong palagay nang maaga sa halip na bayaran ito sa bawat tawag.

Ang pinakakaraniwang convention ay ang bawat group ay hiwalay na Hermitian. Iyon ang nagpapagana sa fermionic randomized product formula sa unang lugar: ang nag-iisang ap†aqa^\dagger_p a_q na may p≠qp \neq q ay hindi Hermitian, kaya hindi unitary ang time evolution nito at hindi ito mase-sample nang mag-isa. Kapag ipinares ito sa aq†apa^\dagger_q a_p, nagkakaroon ng group na maaaring i-sample.

>>> 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]

Isang group index bawat term ang ipinapatupad​

Ang groups array ay may hawak na isang index bawat term, at ang pagtatakda ng array na magkaiba ang haba ay nagtataas ng error. Walang downstream na muling sumusuri sa invariant na ito, kaya ipinapatupad ito sa mismong pagpasok ng mga index sa operator: ang masyadong maikling array ay tahimik na mag-aalis ng mga huling term, at ang masyadong mahaba ay lilikha ng mga group na walang term na nagdadala.

>>> 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

Palaging pinapayagan ang pag-clear ng mga group index sa pamamagitan ng pagtatakda ng None.

Magkahiwalay ang dalawang pagsusuri​

Iniuulat ng groups_have_uniform_coeffs() kung nagkakasundo ang mga coefficient ng isang group, na siyang ipinapalagay ng group_coeff_means() kapag nag-a-average ito ng mga magnitude. Hindi ito mas mahinang bersyon ng pagsusuri sa Hermiticity: walang pagsusuring nagpapahiwatig ng isa pa, sa alinmang direksyon.

>>> 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])

Bilang default, ikinukumpara ang mga magnitude, dahil iyon ang a-average-in ng group_coeff_means(). Ang Hermitian conjugate pair na may mga complex na coefficient ay may magkapantay na magnitude pero hindi magkapantay na coefficient, kaya natutugunan lamang nito ang default na anyo.

>>> 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]
Note

Namamana ng groups_are_hermitian() ang isang-panig na garantiya ng is_hermitian(): laging maaasahan ang entry na True, habang ang entry na False ay maaasahan lamang para sa mga operator type na ang normal form ay tunay na canonical form. Sumangguni sa partikular na operator type para malaman kung alin ang naaangkop.

[1] (1,2)

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