Prinsip reka bentuk perwakilan operator
Panduan ini menerangkan prinsip reka bentuk bersama dan konsep teras yang dikongsi merentasi semua perwakilan operator dalam modul operators.
Gambaran keseluruhan
Perwakilan operator yang disediakan oleh modul ini berkongsi beberapa prinsip reka bentuk asas:
-
Struktur data jarang: Operator hanya mengekod operasi bukan identiti. Susun atur data dalaman secara amnya diilhamkan oleh format data matriks jarang, membolehkan penyimpanan dan pengiraan yang cekap bagi sistem dengan banyak mod tetapi sumbangan penting yang agak sedikit.
-
Lelaran dan pembinaan semula sebutan: Tanpa mengira storan jarang dalaman, operator menyediakan antara muka lelaran yang konsisten, supaya anda boleh memeriksa, menapis dan mentransformasi sebutan tanpa memahami struktur data asas, kemudian membina semula operator baharu daripada sebutan yang diubah suai.
-
Pengindeksan berasaskan mod: Operator menggunakan indeks mod abstrak untuk melabel darjah kebebasan fermion, membolehkan pemetaan fleksibel daripada sistem fizikal kepada perwakilan operator.
-
Pengelompokan sebutan dan hubungan kekomutan: Operator menyokong secara natif maklumat pengelompokan yang mengaitkan sebutan dengan indeks kumpulan. Ini membolehkan pengoptimuman dan pemeliharaan struktur fizikal tanpa memerlukan struktur data berasingan. Lihat panduan pengelompokan untuk penggunaan praktikal.
-
Operasi aritmetik dan matematik: Semua operator melaksanakan set operasi aritmetik yang konsisten (seperti penambahan, pendaraban dan gubahan) dan fungsi matematik dengan menggunakan protokol
OperatorTrait, membolehkan kod seragam merentasi jenis operator berbeza. -
Susunan sebutan operator dan bentuk normal: Operator yang setara secara matematik boleh mempunyai perwakilan dan kelakuan yang sangat berbeza dalam algoritma kuantum. Semua perwakilan operator menyokong pelbagai bentuk normal (berdasarkan hubungan kekomutan khusus algebra) untuk mencapai perwakilan operator yang kanonik, boleh diramal dan boleh dioptimumkan.
Struktur data jarang
Semua operator menggunakan perwakilan jarang di mana hanya operasi bukan identiti dijejaki. Setiap operasi bukan identiti terdiri daripada pekali (nombor kompleks) dan jujukan tindakan pada mod tertentu.
Pendekatan ini mengurangkan penggunaan memori dan masa pengiraan secara dramatik, terutamanya bagi sistem dengan banyak mod tetapi sumbangan penting yang agak sedikit. Dengan hanya mengekod operasi bukan identiti, operasi tertumpu hanya pada apa yang penting, membolehkan kerja dengan sistem besar yang mustahil dengan perwakilan padat. Di samping itu, operator secara semula jadi berskala kepada sebarang bilangan mod; operator yang bertindak pada mod {0, 1} berfungsi tanpa perubahan dalam sistem dengan lebih banyak mod kerana mod yang tidak terjejas secara tersirat ialah identiti.
Sebutan yang serupa dipelihara secara berasingan semasa operasi aritmetik dan mesti digabungkan secara eksplisit jika perlu.
Format storan dalaman
Secara dalaman, operator disimpan dalam tatasusunan yang diilhamkan oleh format data matriks jarang:
-
Tatasusunan pekali: Pekali kompleks bagi setiap sebutan
-
Tatasusunan indeks mod: Mod fermion yang menjadi sasaran setiap tindakan
-
Tatasusunan sempadan: Indeks yang menandakan di mana mod setiap sebutan bermula dan berakhir dalam tatasusunan mod
Tatasusunan tambahan mungkin wujud bergantung pada jenis operator. Sebagai contoh, tika FermionOperator merangkumi tatasusunan tindakan boolean yang menentukan jenis tindakan fermion yang bertindak pada indeks mod berkenaan. Sebaliknya, kelas MajoranaOperator tidak memerlukan pembezaan ini kerana ia mengekod maklumat itu dalam pariti indeks mod. Lihat dokumentasi API untuk jenis operator anda bagi memahami format storan penuh.
Contoh berikut menunjukkan cara tatasusunan ini disusun. Pertama ialah pembinaan langsung menggunakan tatasusunan jarang:
- PYTHON
- C
>>> from qiskit_fermions.operators import FermionOperator
>>>
>>> # Construct operators directly using sparse arrays
>>> # First operator: 1.0 * +0 -1
>>> op1 = FermionOperator(
... coeffs=[1.0],
... actions=[True, False],
... modes=[0, 1],
... boundaries=[0, 2],
... )
>>>
>>> # Second operator: 1.0 * +2 -3
>>> op2 = FermionOperator(
... coeffs=[1.0],
... actions=[True, False],
... modes=[2, 3],
... boundaries=[0, 2],
... )
>>>
>>> # Combine the sparse operators
>>> op1 += op2
>>> print(format(op1))
1.000000e0 +0.000000e0j * (+0 -1)
1.000000e0 +0.000000e0j * (+2 -3)
#include <qiskit_fermions.h>
// Construct first operator: 1.0 * +0 -1
QkComplex64 coeff1[1] = {{1.0, 0.0}};
bool actions1[2] = {true, false};
uint32_t modes1[2] = {0, 1};
uint32_t boundaries1[2] = {0, 2};
QfFermionOperator *op1 = qf_ferm_op_new(1, 2, coeff1, actions1, modes1, boundaries1);
// Construct second operator: 1.0 * +2 -3
QkComplex64 coeff2[1] = {{1.0, 0.0}};
bool actions2[2] = {true, false};
uint32_t modes2[2] = {2, 3};
uint32_t boundaries2[2] = {0, 2};
QfFermionOperator *op2 = qf_ferm_op_new(1, 2, coeff2, actions2, modes2, boundaries2);
// Combine the sparse operators. There is no in-place add in the C API, so
// the sum is a new operator that the caller owns.
QfFermionOperator *sum = qf_ferm_op_add(op1, op2);
qf_ferm_op_free(op1);
qf_ferm_op_free(op2);
qf_ferm_op_free(sum);
Kaedah pembinaan yang mudah
Untuk pembangun Python, tersedia beberapa kaedah pembinaan yang mudah yang mengabstrakkan butiran storan jarang. Kaedah ini memudahkan pembinaan operator tanpa perlu menguruskan tatasusunan pekali, mod dan sempadan:
- PYTHON
- C
>>> from qiskit_fermions.operators import FermionOperator, cre, ann
>>>
>>> # Construct operators using operator algebra notation
>>> op1 = FermionOperator.from_dict({(cre(0), ann(1)): 1.0})
>>> op2 = FermionOperator.from_dict({(cre(2), ann(3)): 1.0})
>>>
>>> # The result is sparse even when combining them
>>> op1 += op2
>>> print(format(op1))
1.000000e0 +0.000000e0j * (+0 -1)
1.000000e0 +0.000000e0j * (+2 -3)
// The C API uses direct array construction; convenience methods are not available.
Pelaksanaan operator tertentu mungkin menyokong kaedah pembinaan tambahan yang sesuai dengan kes penggunaannya. Semak dokumentasi API untuk jenis operator anda bagi melihat semua pilihan pembinaan yang tersedia.
Lelaran sebutan dan pembinaan semula
Operator menyediakan antara muka lelaran yang konsisten dengan menggunakan OperatorTrait.iter_terms() tanpa mengira perwakilan jarang dalamannya. Oleh itu, anda boleh memeriksa, menapis atau mengubah sebutan tanpa perlu memahami struktur data asas. Anda kemudian boleh membina semula operator baharu daripada sebutan yang telah diubah dengan menggunakan OperatorTrait.from_terms().
- PYTHON
- C
>>> from qiskit_fermions.operators import FermionOperator, cre, ann
>>>
>>> # Construct an operator with terms of different orders
>>> op = FermionOperator.from_dict({
... (): 0.5, # constant term (order 0)
... (cre(0), ann(1)): 1.0, # two-body term (order 2)
... (cre(0), cre(1), ann(1), ann(0)): 0.25 # four-body term (order 4)
... })
>>>
>>> # Filter to keep only terms of order 2
>>> order_two_terms = [
... (term, coeff) for term, coeff in op.iter_terms()
... if len(term) == 2
... ]
>>>
>>> # Reconstruct operator from filtered terms
>>> filtered_op = FermionOperator.from_terms(order_two_terms)
>>> print(f"Original operator has {len(op)} terms")
Original operator has 3 terms
>>> print(f"Filtered operator has {len(filtered_op)} term")
Filtered operator has 1 term
// WARNING: Term iteration and filtering are not yet available in the C API.
Pengindeksan berasaskan mod
Semua perwakilan operator merujuk indeks yang dikenakan oleh sebutannya sebagai mod. Mod ialah sekadar indeks yang mengenal pasti satu darjah kebebasan fermionik dalam sistem anda. Pemetaan daripada darjah kebebasan fizikal (seperti orbital ruang, keadaan spin atau nombor kuantum lain) kepada indeks mod diserahkan kepada pengguna, sekali gus membolehkan fleksibiliti maksimum.
Abstraksi ini juga terdapat dalam modul qiskit_fermions.circuit, yang mana FermionicCircuit beroperasi pada daftar mod fermionik. Dalam kedua-dua perwakilan operator dan litar, mod menyediakan cara yang konsisten dan bebas algebra untuk menentukan darjah kebebasan yang mengambil bahagian dalam sesuatu operasi.
Pelaksanaan semasa menggunakan mod tanpa spin: Semua perwakilan operator yang kini disediakan oleh modul ini menganggap mod sebagai darjah kebebasan fermionik tanpa spin. Ini bermakna jika sistem anda mempunyai elektron atau fermion spin-atas dan spin-bawah, anda mesti memetakannya secara eksplisit kepada mod yang berbeza (contohnya, mod 0-3 untuk spin-atas bagi empat orbital ruang, mod 4-7 untuk spin-bawah, atau mana-mana konvensyen lain yang anda pilih).
Reka bentuk ini memastikan perwakilan teras kekal ringkas dan umum sambil mengelak pengenaan konvensyen susunan spin tertentu. Modul utiliti seperti qiskit_fermions.operators.library menyediakan fungsi kemudahan (contohnya, FCIDump.from_file()) yang mengendalikan pemetaan sedemikian untuk anda semasa memuatkan data struktur elektronik.
Apabila pakej ini berkembang, perwakilan operator berspin yang menyokong darjah kebebasan spin secara asli dalam model datanya mungkin ditambah. Perwakilan ini akan dibezakan dengan jelas daripada pelaksanaan tanpa spin semasa dan akan wujud bersama-samanya dalam modul.
Pengumpulan sebutan dan hubungan kekomutan
Seperti pekali dan indeks mod, operator boleh menyimpan tatasusunan kumpulan secara pilihan yang mengaitkan setiap sebutan dengan indeks kumpulan. Dengan mengintegrasikan pengumpulan terus ke dalam perwakilan operator sebagai sebahagian daripada struktur data jarang, maklumat pengumpulan secara semula jadi turut dibawa bersama operator melalui transformasi. Ini membolehkan penggunaan struktur secara sistematik, sama ada daripada sifat fizikal, hubungan algebra atau simetri khusus masalah. Maklumat berstruktur ini kemudian boleh digunakan dalam operasi hiliran seperti sintesis dan penguraian litar dengan menggunakan kaedah seperti OperatorTrait.split_out_groups().
Untuk panduan terperinci tentang cara mengumpulkan sebutan operator dalam aliran kerja anda, lihat panduan pengumpulan.
- PYTHON
- C
>>> from qiskit_fermions.operators import MajoranaOperator, gamma
>>> op = MajoranaOperator.from_dict({
... (gamma(0, False),): 1.0,
... (gamma(1, False),): 1.0,
... (gamma(2, False), gamma(3, False)): 1.0
... })
>>> # Assign group indices to terms
>>> op.groups = [0, 0, 1]
>>> # Partition operator by groups
>>> grouped_ops = op.split_out_groups()
#include <qiskit_fermions.h>
// Create operator with 3 terms
QkComplex64 coeffs[3] = {{1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}};
uint32_t modes[4] = {0, 1, 2, 3};
uint32_t boundaries[4] = {0, 1, 2, 4};
QfMajoranaOperator *op = qf_maj_op_new(3, 4, coeffs, modes, boundaries);
// Assign grouping information
uint32_t groups[3] = {0, 0, 1};
qf_maj_op_set_groups(op, groups, 3);
// Partition operator by groups
QfMajoranaOperator *grouped_ops[2];
qf_maj_op_split_out_groups(op, NULL, 0, grouped_ops);
Operasi aritmetik dan matematik
Semua operator melaksanakan protokol OperatorTrait, yang menyediakan set operasi bersatu merentasi pelbagai jenis operator. Ini memastikan kod yang ditulis untuk satu perwakilan operator berfungsi secara seragam dengan yang lain. Lihat qiskit_fermions.protocols untuk mengetahui bagaimana protokol ini berkaitan dengan protokol lain yang ditakrifkan oleh pakej ini.
Protokol ini merangkumi operasi aritmetik (seperti penambahan, pendaraban dan gubahan), operasi struktur (lelaran sebutan, analisis sokongan mod, pelabelan semula), fungsi matematik (tertib normal, pemudahan, semakan kesetaraan) dan banyak lagi. Lihat dokumentasi OperatorTrait untuk rujukan lengkap semua operasi yang tersedia.
- PYTHON
- C
>>> from qiskit_fermions.operators import FermionOperator, cre, ann
>>>
>>> # Construct a Hermitian operator: H = +0 -1 + +1 -0
>>> op = FermionOperator.from_dict({
... (cre(0), ann(1)): 1.0,
... (cre(1), ann(0)): 1.0
... })
>>>
>>> # Check if the operator is Hermitian
>>> print(f"Operator is Hermitian: {op.is_hermitian(atol=1e-10)}")
Operator is Hermitian: True
#include <qiskit_fermions.h>
// Construct a Hermitian operator: H = +0 -1 + +1 -0
QkComplex64 coeffs[2] = {{1.0, 0.0}, {1.0, 0.0}};
bool actions[4] = {true, false, true, false};
uint32_t modes[4] = {0, 1, 1, 0};
uint32_t boundaries[3] = {0, 2, 4};
QfFermionOperator *op = qf_ferm_op_new(2, 4, coeffs, actions, modes, boundaries);
// Check if the operator is Hermitian
bool is_hermitian = qf_ferm_op_is_hermitian(op, 1e-10);
printf("Operator is Hermitian: %s\n", is_hermitian ? "true" : "false");
// Clean up
qf_ferm_op_free(op);
is_hermitian() mengesahkan bahawa dengan mengurangkan perbezaan itu kepada bentuk normal dan membandingkannya dengan zero(). Dihuraikan dalam bentuk operasi protokol yang lain, ia melaksanakan perkara berikut:
>>> difference = (op - op.adjoint()).normal_ordered().simplify(atol=1e-10)
>>> difference.equiv(FermionOperator.zero(), atol=1e-10)
True
Kekuatan semakan ini bergantung pada jenis operator, kerana ia bergantung pada sejauh mana lengkap bentuk normal jenis tersebut mengecutkan penjana bersebelahan. Keputusan True sentiasa boleh dipercayai, tetapi bagi sesetengah jenis keputusan False bersifat konservatif: lihat is_hermitian() untuk butiran.
Contoh ini menggunakan atol=1e-10. Parameter atol (toleransi mutlak) menentukan satu ambang. Pekali dengan magnitud lebih kecil daripada atol dianggap sifar dan dibuang. Ini penting untuk kestabilan berangka apabila membandingkan operator, kerana aritmetik titik terapung boleh menimbulkan ralat pembundaran kecil yang sebaliknya menghalang operator setara daripada dikenali sedemikian.
Walaupun protokol OperatorTrait menyediakan antara muka sepunya, pelaksanaan operator tertentu mungkin menawarkan kaedah kemudahan tambahan yang bukan sebahagian daripada protokol. Contohnya, FermionOperator dan MajoranaOperator menyediakan kaedah max_rank() yang melaporkan panjang sebutan terpanjang mereka. Sentiasa rujuk dokumentasi API untuk jenis operator anda bagi mengetahui semua fungsi yang tersedia.
Susunan sebutan operator dan bentuk normal
Cabaran asas dalam algebra operator kuantum ialah operator yang setara secara matematik boleh diwakili dalam pelbagai cara, masing-masing dengan implikasi berbeza untuk algoritma kuantum. Operator yang sama boleh ditulis dalam bentuk yang setara secara algebra (contohnya, boleh dinyatakan sebagai ), namun perwakilan ini menghasilkan tingkah laku yang berbeza dalam sintesis litar, pemudahan dan algoritma berangka.
Perwakilan operator menyokong operasi tertib normal yang mengubah operator kepada bentuk kanonik khusus algebra menggunakan hubungan kekomutan. Ini membolehkan perbandingan yang boleh dipercayai (dua operator setara mempunyai bentuk tertib normal yang sama), mendedahkan pemudahan (hubungan kekomutan menyebabkan sebutan saling membatalkan atau bergabung), dan menyokong algoritma yang memerlukan bentuk operator tertentu demi ketepatan dan kecekapan.
Perwakilan operator yang berbeza mungkin melaksanakan tertib normal berdasarkan hubungan kekomutan berbeza yang sesuai dengan algebra mereka. Contohnya, tertib normal fermionik menggunakan hubungan antikekomutan (), manakala tertib normal Majorana menggunakan konvensyen algebra yang berbeza (). Sentiasa rujuk dokumentasi untuk jenis operator anda bagi memahami cara tertib normal dilaksanakan.
- PYTHON
- C
>>> from qiskit_fermions.operators import FermionOperator, cre, ann
>>>
>>> # Two different representations of the same operator
>>> op1 = FermionOperator.from_dict({(ann(0), cre(0)): 1.0})
>>> op2 = FermionOperator.from_dict({(): 1.0, (cre(0), ann(0)): -1.0})
>>>
>>> # Direct comparison fails due to different forms
>>> op1.equiv(op2, atol=1e-10)
False
>>>
>>> # Normal-order both and compare again
>>> op1_normal = op1.normal_ordered()
>>> op2_normal = op2.normal_ordered()
>>> op1_normal.equiv(op2_normal, atol=1e-10)
True
#include <qiskit_fermions.h>
#include <stdbool.h>
// Two different representations of the same operator
QkComplex64 coeff1[1] = {{1.0, 0.0}};
bool actions1[2] = {false, true};
uint32_t modes1[2] = {0, 0};
uint32_t boundaries1[2] = {0, 2};
QfFermionOperator *op1 = qf_ferm_op_new(1, 2, coeff1, actions1, modes1, boundaries1);
QkComplex64 coeff2[2] = {{1.0, 0.0}, {-1.0, 0.0}};
bool actions2[2] = {true, false};
uint32_t modes2[2] = {0, 0};
uint32_t boundaries2[3] = {0, 0, 2};
QfFermionOperator *op2 = qf_ferm_op_new(2, 2, coeff2, actions2, modes2, boundaries2);
// Direct comparison fails due to different forms
bool equiv_before = qf_ferm_op_equiv(op1, op2, 1e-10);
printf("Equivalent before normal ordering: %s\n", equiv_before ? "true" : "false");
// Normal-order both and compare again
QfFermionOperator *op1_normal = qf_ferm_op_normal_ordered(op1, NULL);
QfFermionOperator *op2_normal = qf_ferm_op_normal_ordered(op2, NULL);
bool equiv_after = qf_ferm_op_equiv(op1_normal, op2_normal, 1e-10);
printf("Equivalent after normal ordering: %s\n", equiv_after ? "true" : "false");
// Clean up
qf_ferm_op_free(op1);
qf_ferm_op_free(op2);
qf_ferm_op_free(op1_normal);
qf_ferm_op_free(op2_normal);
Kaedah protokol OperatorTrait.normal_ordered() sengaja membiarkan argumen kedudukan dan kata kuncinya tidak dinyatakan, supaya pelaksanaan operator konkrit dapat mentakrifkan parameter boleh laras yang mengawal bentuk kanonik tepat yang dihasilkan. Ini membolehkan pengoptimuman khusus operator dan varian bentuk normal yang disesuaikan dengan algebra atau kes penggunaannya. Semak dokumentasi API untuk jenis operator anda bagi melihat parameter yang tersedia.