Cum se raportează acest pachet la ffsim
Conceptele din acest ghid sunt disponibile doar în API-ul Python.
ffsim și acest pachet își împart munca, în loc să se suprapună, de-a lungul unei singure linii:
| ffsim se ocupă de | qiskit-fermions se ocupă de |
|---|---|
Operatorii ansatz de nivel înalt (UCJOpSpinBalanced, UCCSDOpRestrictedReal și variantele lor), construiți din amplitudini coupled-cluster sau dintr-un vector de parametri | Circuitul fermionic (FermionicCircuit) în care devin acei operatori și transpilarea lui într-un circuit pe qubiți, sub orice codificare fermion-qubit |
| Simulare rapidă într-un spațiu compact cu număr fix de particule | Cadrul de mapare și structurile de date ale operatorilor din care este construit circuitul |
Consecința practică funcționează în ambele sensuri. Matematica ansatz-ului se află în ffsim, așa că UCJ și UCC primesc direct un operator ffsim ca intrare. Invers, porțile Qiskit proprii ale ffsim sunt specifice transformării Jordan-Wigner, așa că ceea ce îți oferă aducerea unuia dintre operatorii săi ansatz aici este coborârea lui printr-o codificare diferită.
Simularea este locul unde se întâlnesc cei doi, iar acest ghid explică cum. ffsim este backend-ul de simulare al acestui pachet, accesat prin propriile protocoale, nu printr-un wrapper: ghidul SKQD apelează ffsim.apply_unitary(), ffsim.linear_operator() și ffsim.sample_state_vector() direct pe obiecte FermionicCircuit și pe obiecte FermionOperator, fără niciun pas de conversie.
Conectarea la interfața de simulare a ffsim
ffsim este un simulator de înaltă performanță pentru circuite cuantice fermionice, care exploatează conservarea numărului de particule și a spinului Z pentru a reprezenta vectorii de stare mai compact decât un vector de stare generic pe qubiți de dimensiune . Definește protocoale pe care orice obiect le poate implementa pentru a participa la mecanismul său de simulare (vezi qiskit_fermions.protocols pentru protocoalele proprii ale acestui pachet, care urmează același design):
-
ffsim.SupportsApplyUnitary, prin metoda_apply_unitary_(vec, norb, nelec, copy), care aplică obiectul ca unitar unui vector de stare cu număr fix de particule -
ffsim.SupportsLinearOperator, prin metoda_linear_operator_(norb, nelec), care returnează o vederescipy.sparse.linalg.LinearOperatora obiectului în același sector -
ffsim.SupportsTrace, prin metoda_trace_(norb, nelec), care returnează urma obiectului în acel sector.
Acest pachet implementează acea interfață: fiecare poartă fermionică din qiskit_fermions.circuit.library oferă _apply_unitary_, iar FermionOperator oferă _linear_operator_ și _trace_. Aceasta face operatorii și circuitele acestui pachet compatibile cu ffsim, astfel încât instrumentele sale funcționează nativ pe ele, fără niciun pas de conversie. ffsim.apply_unitary() poate simula un FermionicCircuit de la un capăt la altul, ffsim.linear_operator() poate diagonaliza un FermionOperator, iar utilitarele de eșantionare precum ffsim.sample_state_vector() (folosit în ghidul SKQD pentru a transforma un vector de stare simulat în numărători de măsurare) funcționează fără modificări.
Ceea ce returnează _linear_operator_ este un LinearOperator SciPy obișnuit, deci scipy.sparse.linalg.eigsh() și funcțiile similare funcționează și pe el.
>>> import ffsim
>>> import numpy as np
>>>
>>> from qiskit_fermions.circuit import FermionicCircuit
>>> from qiskit_fermions.circuit.library import Evolution
>>> from qiskit_fermions.operators import FermionOperator, ann, cre
>>>
>>> norb, nelec = 2, (1, 1)
>>> hamiltonian = FermionOperator.from_terms([
... ([cre(0), ann(1)], 0.5),
... ([cre(1), ann(0)], 0.5),
... ])
>>>
>>> circuit = FermionicCircuit(2 * norb)
>>> circuit.append(Evolution(2 * norb, hamiltonian, time=1.0), circuit.modes)
>>>
>>> reference = ffsim.hartree_fock_state(norb, nelec)
>>> state = ffsim.apply_unitary(reference, circuit, norb=norb, nelec=nelec) # native ffsim call
Cuplarea prin protocoalele ffsim este ceea ce aduce acest lucru: ecosistemul său de utilitare de simulare și eșantionare, dezvoltat activ, se aplică neschimbat circuitelor și operatorilor acestui pachet, iar utilizatorii care lucrează deja cu ffsim pot amesteca porțile și operatorii acestui pachet fără să învețe un alt API de simulare.
ffsim este o dependență opțională
ffsim este declarat ca extra opțional (pip install "qiskit-fermions[ffsim]", sau tranzitiv prin [all]), protejat la runtime de HAS_FFSIM (așa cum s-a arătat mai sus). Instalarea lui deblochează simularea: ffsim.SupportsLinearOperator și ffsim.SupportsTrace sunt implementate prin conversia FermionOperator-ului acestui pachet într-un ffsim.FermionOperator, deci fără ffsim ele ridică MissingOptionalLibraryError. Tot ce nu simulează (construirea operatorilor, maparea lor și transpilarea circuitelor rezultate) nu are nevoie de nimic din toate acestea.
Simularea fermionică se desfășoară într-un sector cu număr fix de particule
Atât _apply_unitary_, cât și _linear_operator_ primesc un argument nelec și reprezintă vectorul de stare peste baza de determinanți cu număr fix de particule pentru acel sector (norb, nelec), oglindind configurarea spațiului FCI din ffsim (și, tranzitiv, din PySCF), în loc de spațiul complet de dimensiune pe care l-ar folosi un simulator generic de qubiți. Acesta este un spațiu mult mai mic (dimensiunea lui este un produs de coeficienți binomiali, nu o putere a lui doi), dar vine cu o restricție strictă. Doar operatorii și porțile care păstrează numărul de particule (și, în cazul cu spin, numărul de particule al fiecărei specii de spin individual) pot fi reprezentate în el. Un operator a cărui acțiune ar muta amplitudine către un alt număr de particule nu are unde să o pună.
ffsim rezolvă aceasta respingând de-a dreptul un astfel de operator: conversia unuia într-un operator liniar ridică o ValueError care numește ce lege de conservare eșuează. Aceasta este opțiunea implicită corectă, deoarece aplicarea lui pentru un Hamiltonian cu un termen care nu conservă numărul de particule ar transforma altfel o aplicație care ar fi unitară într-una neunitară, fără sens fizic.
-
Evolutionscoate la suprafață acea respingere din operatorul pe care îl evoluează. -
OrbitalRotationverifică dacă matricea sa de rotație (încorporată) este bloc-diagonală pe împărțirea alfa/beta în cazul cu spin și generează o eroareValueErrordacă aceasta amestecă sectoarele de spin.
>>> from qiskit_fermions.circuit.library import Evolution
>>>
>>> non_conserving = FermionOperator.from_terms([([cre(0), cre(1)], 1.0)]) # creates 2 particles
>>> gate = Evolution(2 * norb, non_conserving, time=1.0)
>>>
>>> try:
... gate._apply_unitary_(reference, norb, nelec, copy=True)
... except ValueError as exc:
... print("rejected:", exc)
rejected: The given FermionOperator could not be converted to a LinearOperator because it does not conserve particle number and the z component of spin. Conserves particle number: False Conserves spin z: False
Prin urmare, simularea care nu conservă numărul de particule este imposibilă în spațiul fermionic, prin construcția reprezentării cu sector fix, iar acesta este prețul spațiului FCI compact care face simularea fermionică tratabilă încă de la început. Dacă algoritmul tău are nevoie de operatori care încalcă numărul de particule (de exemplu, un canal de eroare nativ pentru qubiți sau un operator construit pentru un Hamiltonian mapat care nu conservă numărul de particule termen cu termen), transpilează mai întâi la qubiți și simulează în schimb QuantumCircuit rezultat cu un simulator la nivel de qubit. Orice rută de transpilare funcționează pentru aceasta; ghidurile despre circuite fermionice și transpilare oferă mai multe detalii, dar generate_preset_jw_pass_manager() este o alegere implicită rezonabilă.
Convenția block-spin pentru sistemele cu spin
nelec are tipul int | tuple[int, int], iar tipul său, nu un indicator separat, este cel care selectează unul dintre aranjamentele de moduri acceptate:
-
Un int selectează interpretarea fără spin. Cele
norbmoduri sunt tratate direct ca orbitali fără spin, iarneleceste numărul total de particule. -
O pereche
(n_alpha, n_beta)selectează interpretarea cu spin a celor2 * norbmoduri sub o convenție block-spin fixă. Modurile0 .. norbsunt orbitalii alfa (spin sus), iar modurilenorb .. 2 * norbsunt orbitalii beta (spin jos). Fiecare specie de spin este conservată independent; un termen doar alfa poate muta un electron între moduri alfa, dar niciodată într-un mod beta, și invers.
Această distribuire are loc în fiecare punct de intrare al protocolului ffsim din acest pachet (constructorii de porți, implementările _apply_unitary_placed_ și compilarea sectoarelor a nucleului nativ Rust) și este convenția folosită în ghidurile LUCJ și SKQD (de exemplu, InitializeModes.from_hartree_fock() plasează ocupările alfa în modurile 0 .. n_alpha și ocupările beta în modurile norb .. norb + n_beta). Merită comparată cu modulul qiskit_fermions.operators și cu FermionicCircuit în general, care folosesc indici de mod generici, fără semantică de spin inerentă (vezi ghidul circuitelor fermionice). Semnificația block-spin este impusă doar atunci când un nelec cu spin este furnizat unui apel de simulare, nu este încorporată în reprezentarea operatorului sau a circuitului în sine.
>>> from qiskit_fermions.circuit.library import InitializeModes
>>>
>>> norb, nelec = 3, (2, 1)
>>> init = InitializeModes.from_hartree_fock(norb, nelec)
>>> print([bool(occ) for occ in init.occupation]) # alpha modes 0,1; beta mode 3 (= norb + 0)
[True, True, False, True, False, False]
Pașii următori
-
Parcurge ghidul SKQD pentru a vedea
ffsim.apply_unitary()șiffsim.sample_state_vector()folosite împreună pentru a eșantiona circuite construite din porțile acestui pachet și pentru a evalua o valoare medie a unui Hamiltonian prinffsim.linear_operator()(susținut la rândul său de aceeași metodă de protocol_linear_operator_descrisă aici). -
Parcurge ghidul LUCJ pentru cealaltă jumătate a poveștii: preluarea unui operator de ansatz ffsim prin pipeline-ul de transpilare al acestui pachet și aducerea lui pe o hartă de cuplare a dispozitivului.
-
Citește ghidul circuitelor fermionice pentru indexarea generică a modurilor, agnostică față de spin, folosită în afara apelurilor de simulare.
-
Citește ghidul de transpilare pentru a afla cum părăsești spațiul fermionic
și simulezi pe qubiți, ceea ce este necesar pentru operatorii care nu conservă particulele.
-
Explorează
qiskit_fermions.protocolspentru catalogul complet de protocoale definite de acest pachet, inclusiv protocoalele de conversie (SupportsFermionOperator,SupportsMajoranaOperator) care nu au legătură cu ffsim. -
Citește ghidurile proprii ale ffsim pentru fluxurile de lucru pe care le deține, în special construirea unui ansatz UCJ și optimizarea lui variațională. Vectorii de parametri pe care îi manipulează aceste ghiduri sunt cei pe care
UCJșiUCCîi acceptă, prin operatorii pe care îi construiesc.