Jak tento balíček souvisí s ffsim
Koncepty v tomto průvodci jsou dostupné pouze v Python API.
ffsim a tento balíček si práci dělí, nikoli překrývají, podle jediné hranice:
| ffsim vlastní | qiskit-fermions vlastní |
|---|---|
Vysokoúrovňové operátory ansatzů (UCJOpSpinBalanced, UCCSDOpRestrictedReal a jejich sourozenci), sestavené z amplitud coupled-cluster nebo z vektoru parametrů | Fermionický obvod (FermionicCircuit), v nějž se tyto operátory změní, a jeho transpilaci na qubitový obvod v libovolném kódování fermion-na-qubit |
| Rychlá simulace v kompaktním prostoru s pevným počtem částic | Framework mapperů a datové struktury operátorů, z nichž se obvod sestavuje |
Praktický důsledek platí oběma směry. Matematika ansatzů žije v ffsim, takže UCJ a UCC berou jako vstup přímo operátor z ffsim. Naopak vlastní hradla Qiskit z ffsim jsou specifická pro Jordanovu-Wignerovu transformaci, takže přenesení jeho operátoru ansatzu sem ti přináší možnost převést ho přes jiné kódování.
Simulace je místo, kde se obě setkávají, a tento průvodce vysvětluje jak. ffsim je simulační backend tohoto balíčku, dostupný přes vlastní protokoly, nikoli přes obal: průvodce SKQD volá ffsim.apply_unitary(), ffsim.linear_operator() a ffsim.sample_state_vector() přímo na objektech FermionicCircuita FermionOperatorbez jakéhokoli kroku převodu.
Připojení k simulačnímu rozhraní ffsim
ffsim je vysoce výkonný simulátor fermionických kvantových obvodů, který využívá zachování počtu částic a spinu Z k reprezentaci stavových vektorů kompaktněji než obecný -rozměrný qubitový stavový vektor. Definuje protokoly, které může implementovat jakýkoli objekt, aby se zapojil do jeho simulačního aparátu (viz qiskit_fermions.protocols pro vlastní protokoly tohoto balíčku, které sledují stejný návrh):
-
ffsim.SupportsApplyUnitarypomocí metody_apply_unitary_(vec, norb, nelec, copy), která aplikuje objekt jako unitární operaci na stavový vektor s pevným počtem částic -
ffsim.SupportsLinearOperatorpomocí metody_linear_operator_(norb, nelec), která vrací pohled na objekt v témže sektoru jakoscipy.sparse.linalg.LinearOperator -
ffsim.SupportsTracepomocí metody_trace_(norb, nelec), která vrací stopu objektu v tomto sektoru.
Tento balíček toto rozhraní implementuje: každé fermionické hradlo v qiskit_fermions.circuit.library poskytuje _apply_unitary_ a FermionOperator poskytuje _linear_operator_ a _trace_. Právě to činí operátory a obvody tohoto balíčku kompatibilními s ffsim, takže jeho nástroje na nich fungují nativně, bez kroku převodu. ffsim.apply_unitary() může simulovat FermionicCircuit od začátku do konce, ffsim.linear_operator() může diagonalizovat FermionOperator a vzorkovací nástroje jako ffsim.sample_state_vector() (použitý v průvodci SKQD k převodu simulovaného stavového vektoru na počty měření) fungují bez úprav.
To, co vrací _linear_operator_, je běžný LinearOperator ze SciPy, takže na něm fungují i scipy.sparse.linalg.eigsh() a další.
>>> 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
Právě propojení přes protokoly ffsim to umožňuje: jeho aktivně vyvíjený ekosystém simulačních a vzorkovacích nástrojů se na obvody a operátory tohoto balíčku vztahuje beze změny a uživatelé, kteří už s ffsim pracují, mohou přimíchat hradla a operátory tohoto balíčku, aniž by se museli učit další simulační API.
ffsim je volitelná závislost
ffsim je deklarován jako volitelný extra (pip install "qiskit-fermions[ffsim]", nebo tranzitivně přes [all]), hlídaný za běhu pomocí HAS_FFSIM (jak bylo ukázáno výše). Jeho instalace odemkne simulaci: ffsim.SupportsLinearOperator a ffsim.SupportsTrace jsou implementovány převodem FermionOperator tohoto balíčku na ffsim.FermionOperator, takže bez ffsim vyvolají MissingOptionalLibraryError. Nic, co nesimuluje (sestavování operátorů, jejich mapování a transpilace výsledných obvodů), ho nepotřebuje.
Fermionická simulace probíhá v sektoru s pevným počtem částic
_apply_unitary_ i _linear_operator_ přijímají argument nelec a reprezentují stavový vektor v determinantové bázi s pevným počtem částic pro daný sektor (norb, nelec), v souladu s nastavením prostoru FCI v ffsim (a tranzitivně v PySCF), místo celého -rozměrného prostoru, který by použil obecný qubitový simulátor. Je to mnohem menší prostor (jeho velikost je součinem binomických koeficientů, nikoli mocninou dvou), ale přichází s tvrdým omezením. Lze v něm reprezentovat jen operátory a hradla, která zachovávají počet částic (a v případě se spinem počet částic každého spinového druhu zvlášť). Operátor, jehož působení by přesunulo amplitudu na jiný počet částic, pro ni nemá kam dát.
ffsim to řeší tím, že takový operátor rovnou odmítne: jeho převod na lineární operátor vyvolá ValueError s uvedením, který zákon zachování selhává. To je správné výchozí chování, protože aplikace pro hamiltonián s členem nezachovávajícím počet částic by jinak změnila údajně unitární mapu na neunitární a fyzikálně bezvýznamnou.
-
Evolutiontoto odmítnutí přebírá od operátoru, který vyvíjí. -
OrbitalRotationkontroluje, že jeho (vnořená) rotační matice je ve spinovém případě blokově diagonální vzhledem k rozdělení alfa/beta, a pokud míchá spinové sektory, vyvoláValueError.
>>> 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
Simulace, která nezachovává počet částic, je proto ve fermionovém prostoru z principu nedosažitelná, a to kvůli reprezentaci s pevným sektorem; je to cena za kompaktní prostor FCI, který vůbec umožňuje fermionovou simulaci zvládnout. Pokud tvůj algoritmus potřebuje operátory porušující počet částic (například kanál chyb nativní pro qubity nebo operátor sestavený pro namapovaný hamiltonián, který nezachovává počty částic člen po členu), nejprve transpiluj na qubity a výsledný QuantumCircuit simuluj místo toho simulátorem na úrovni qubitů. Funguje k tomu jakákoli cesta transpilace; podrobněji se jí věnují průvodci fermionovým obvodem a transpilací, ale rozumnou výchozí volbou je generate_preset_jw_pass_manager().
Bloková spinová konvence pro spinové systémy
nelec má typ int | tuple[int, int] a právě jeho typ, nikoli samostatný příznak, určuje, které z podporovaných uspořádání módů se použije:
-
int vybírá bezspinovou interpretaci.
norbmódů se bere přímo jako bezspinové orbitaly anelecje celkový počet částic. -
Dvojice
(n_alpha, n_beta)vybírá spinovou interpretaci2 * norbmódů podle pevné blokové spinové konvence. Módy0 .. norbjsou orbitaly alfa (spin nahoru) a módynorb .. 2 * norbjsou orbitaly beta (spin dolů). Každý druh spinu se zachovává nezávisle; člen jen s alfa může přesunout elektron mezi módy alfa, ale nikdy do módu beta, a naopak.
Toto rozlišení probíhá v každém vstupním bodě protokolu ffsim v tomto balíčku (konstruktory hradel, implementace _apply_unitary_placed_ a kompilace sektorů v nativním jádru v Rustu) a je to konvence používaná v celých průvodcích LUCJ a SKQD (například InitializeModes.from_hartree_fock() zapisuje obsazení alfa do módů 0 .. n_alpha a obsazení beta do módů norb .. norb + n_beta). Stojí za to to porovnat s modulem qiskit_fermions.operators a obecně s FermionicCircuit, které používají obecné indexy módů bez vlastního spinového významu (viz průvodce fermionovým obvodem). Blokový spinový význam se uplatní až ve chvíli, kdy se volání simulace předá spinové nelec, nikoli přímo v reprezentaci operátoru nebo obvodu.
>>> 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]
Další kroky
-
Projdi si průvodce SKQD, kde uvidíš
ffsim.apply_unitary()affsim.sample_state_vector()použité společně pro vzorkování obvodů sestavených z hradel tohoto balíčku a také vyhodnocení střední hodnoty hamiltoniánu pomocíffsim.linear_operator()(který sám stojí na téže metodě protokolu_linear_operator_popsané zde). -
Projdi si průvodce LUCJ, který ukazuje druhou polovinu příběhu: jak se ansatz operátor z ffsim převede transpilačním řetězcem tohoto balíčku na souvislosti zařízení (coupling map).
-
Přečti si průvodce fermionovým obvodem, kde najdeš obecné indexování módů bez ohledu na spin, které se používá mimo volání simulace.
-
Přečti si průvodce transpilací, jak opustit fermionový prostor
a simulovat na qubitech, což je nutné pro operátory, které nezachovávají počet částic.
-
Prohlédni si
qiskit_fermions.protocols, kde najdeš úplný katalog protokolů definovaných tímto balíčkem, včetně konverzních protokolů (SupportsFermionOperator,SupportsMajoranaOperator), které s ffsim nesouvisejí. -
Přečti si vlastní průvodce ffsim k pracovním postupům, které spravuje, zejména sestavení ansatzu UCJ a jeho variační optimalizaci. Vektory parametrů, se kterými tito průvodci pracují, jsou to, co
UCJaUCCpřijímají prostřednictvím operátorů, které sestavují.