Kumpulkan sebutan operator: gunakan struktur operator
Pengumpulan ialah salah satu operasi di bawah qiskit_fermions.operators.terms, yang menghimpunkan rutin yang membahagikan sebutan operator berdasarkan strukturnya.
Seperti yang diterangkan dalam panduan operator, operator boleh menyimpan tatasusunan kumpulan, bahagian pilihan struktur data jarang yang mengaitkan setiap sebutan dengan indeks kumpulan. Sebutan yang berkongsi indeks kumpulan yang sama membentuk satu kumpulan. Ini membolehkan anda memanfaatkan struktur tersebut secara sistematik dalam pemprosesan hiliran.
Dengan mengumpulkan sebutan yang berkaitan (sama ada mengikut sifat fizikal, hubungan algebra, atau simetri khusus masalah), anda boleh membuka beberapa faedah:
-
Sintesis litar yang dioptimumkan: Sebutan berkumpulan membawa maklumat khusus masalah melalui tindanan, membolehkan pengoptimuman litar tersintesis yang lebih mudah. Ini menghasilkan kedalaman litar dan bilangan gate yang berkurangan.
-
Pemeliharaan struktur fizikal: Kumpulan mengekodkan struktur bermakna daripada masalah asal (contohnya, corak interaksi atau simetri) yang boleh digunakan untuk penguraian yang lebih bermakna dari segi fizikal.
-
Pemilihan set aliran: Pengumpulan secara semula jadi boleh mengekodkan set aliran dan struktur teori graf lain yang relevan untuk simulasi kuantum, seperti yang ditunjukkan dalam [1].
-
Kestabilan algoritma yang lebih baik: Seperti yang ditunjukkan dalam rutin SqDRIFT, sesetengah algoritma boleh mendapat manfaat daripada kestabilan atau prestasi yang lebih baik kerana pemeliharaan sifat fizikal.
-
Faktor formula hasil darab: Formula hasil darab fermionik membahagikan operator kepada kumpulannya, jadi pengumpulan menentukan kos dan ralat Trotter bagi evolusi masa. Lihat Sintesis gate Evolution dalam ruang fermionik.
Penggunaan
Cara paling mudah untuk menentukan pengumpulan operator ialah dengan menetapkan atribut groups bagi operator sasaran. Berikut ialah contoh untuk mengumpulkan sebutan mengikut set aliran garisan seperti yang ditunjukkan dalam Rajah 1c [1].
Modul qiskit_fermions.operators.terms.grouping menyediakan kaedah kemudahan untuk mengenal pasti struktur dalam operator secara automatik dan menetapkan indeks kumpulan dengan sewajarnya.
>>> 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>
Ini ialah kekisi dua kali tiga bagi mod Majorana yang disambungkan oleh tepi berarah. Setiap tepi mewakili satu sebutan dalam operator yang bertindak ke atas dua mod yang disambungkan. Matlamatnya ialah mengumpulkan sebutan ini mengikut label tepinya (ditunjukkan pada graf). Sebutan yang disambungkan oleh tepi dengan label yang sama diletakkan dalam kumpulan yang sama. Kod berikut menunjukkan cara melakukannya:
- PYTHON
- C
>>> 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))]
#include <qiskit_fermions.h>
uint64_t num_terms = 7;
uint64_t num_modes = 14;
uint32_t modes[14] = {0, 1, 1, 2, 3, 0, 1, 4, 5, 2, 5, 4, 4, 3};
QkComplex64 coeffs[7] = {{1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0},
{1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}};
uint32_t boundaries[8] = {0, 2, 4, 6, 8, 10, 12, 14};
QfMajoranaOperator *op = qf_maj_op_new(num_terms, num_modes, coeffs, modes, boundaries);
uint32_t groups[7] = {0, 0, 1, 2, 1, 3, 3};
qf_maj_op_set_groups(op, groups, num_terms);
QfMajoranaOperator *group_ops[4];
qf_maj_op_split_out_groups(op, NULL, 0, group_ops);
Analisis pengumpulan
Kumpulan tidak menetapkan sebarang makna sendiri: tatasusunan kumpulan hanya merekodkan sebutan mana yang tergolong bersama, tidak pernah sebabnya. Tiada rutin dalam pustaka ini yang melaporkan sama ada sesuatu pengumpulan itu “betul”, kerana tiada satu pun tanggapan kebetulan yang boleh dijadikan rujukan. Namun, pengguna hiliran mengandaikan sifat tertentu bagi sesuatu pengumpulan, dan fungsi dalam bahagian ini membolehkan anda menyemak andaian sedemikian terlebih dahulu dan bukannya menanggung kosnya pada setiap panggilan.
Konvensyen yang paling lazim ialah setiap kumpulan adalah Hermitian secara berasingan. Itulah yang menjadikan formula hasil darab rawak fermionik mungkin: yang bersendirian dengan bukan Hermitian, jadi evolusi masanya bukan uniter dan ia tidak boleh disampel secara berasingan. Memasangkannya dengan menghasilkan kumpulan yang boleh disampel.
- PYTHON
- C
>>> 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]
#include <qiskit_fermions.h>
uint64_t num_terms = 3;
uint64_t num_actions = 6;
bool actions[6] = {true, false, true, false, true, false};
uint32_t modes[6] = {0, 1, 1, 0, 2, 3};
QkComplex64 coeffs[3] = {{1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}};
uint32_t boundaries[4] = {0, 2, 4, 6};
QfFermionOperator *op =
qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
uint32_t groups[3] = {0, 0, 1};
qf_ferm_op_set_groups(op, groups, num_terms);
bool hermitian[2];
qf_ferm_op_groups_are_hermitian(op, 1e-8, hermitian);
double means[2];
qf_ferm_op_group_coeff_means(op, means);
Satu indeks kumpulan bagi setiap sebutan dikuatkuasakan
Tatasusunan kumpulan memegang satu indeks bagi setiap sebutan, dan menetapkan tatasusunan yang panjangnya berbeza akan menimbulkan ralat. Tiada apa-apa di hiliran yang menyemak semula invarian ini, jadi ia dikuatkuasakan di tempat indeks memasuki operator: tatasusunan yang terlalu pendek akan menggugurkan sebutan akhir secara senyap, dan yang terlalu panjang akan mereka kumpulan yang tidak dibawa oleh sebarang sebutan.
>>> 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
Mengosongkan indeks kumpulan dengan menetapkan None sentiasa dibenarkan.
Kedua-dua semakan adalah bebas
groups_have_uniform_coeffs() melaporkan sama ada pekali sesuatu kumpulan sepadan, iaitu andaian yang dibuat oleh group_coeff_means() apabila ia memurnikan magnitud. Ia bukan bentuk yang lebih lemah bagi semakan Hermiticity: tiada satu pun semakan menyiratkan yang lain, dalam kedua-dua arah.
>>> 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])
Secara lalai magnitud dibandingkan, kerana itulah yang dipurata oleh group_coeff_means(). Pasangan konjugat Hermitian dengan pekali kompleks mempunyai magnitud yang sama tetapi pekali yang tidak sama, jadi ia hanya memenuhi bentuk lalai.
>>> 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]
groups_are_hermitian() mewarisi jaminan sebelah pihak bagi is_hermitian(): entri True sentiasa boleh dipercayai, manakala entri False hanya boleh dipercayai untuk jenis operator yang bentuk normalnya ialah bentuk kanonik sebenar. Rujuk jenis operator tertentu untuk mengetahui yang mana satu terpakai.
A. Gandon et al., Stabilizer-based quantum simulation of fermion dynamics with local qubit encodings, arXiv:2512.11418v2.