Přeskočit na hlavní obsah
Tento projekt je v betě. Našel jsi chybu? Otevřít issue na GitHubu. Máš otázku nebo nápad? Zeptej se v Discussions — rádi si poslechneme tvou zpětnou vazbu!
Jaká je kvalita překladu na této stránce?

Práce s fermionickými obvody

Důležité

Koncepty v tomto průvodci jsou aktuálně dostupné pouze v Python API. Ekvivalentní funkcionalita bude v C API zpřístupněna v budoucím vydání.

Tento průvodce vysvětluje, jak použít FermionicCircuit k implementaci kvantových algoritmů přímo ve fermionickém prostoru, místo aby se nejdříve mapovalo na qubity.

Proč používat fermionické obvody​

Uvažuj tradiční postup implementace časového vývoje fermionického hamiltoniánu na architektuře založené na qubitech:

  1. Definuj fermionický hamiltonián (například H=∑pqhpqcp†cqH = \sum_{pq} h_{pq} c^\dagger_p c_q).

  2. Namapuj ho na qubitový operátor (například pomocí Jordanova-Wignerova mapování).

  3. Implementuj časový vývoj v qubitovém prostoru (pomocí trotterizace nebo jiných metod).

Tento přístup má zásadní omezení: brzké mapování na qubity zahazuje znalosti o fermionické struktuře problému. Standardní optimalizační průchody nemohou využít fermionické symetrie ani povolená přeuspořádání členů, což vede k suboptimálním obvodům s zbytečnou hloubkou a počtem hradel.

FermionicCircuit umožňuje lepší postup:

  1. Definuj fermionický hamiltonián (například H=∑pqhpqcp†cqH = \sum_{pq} h_{pq} c^\dagger_p c_q).

  2. Implementuj časový vývoj přímo ve fermionickém prostoru pomocí fermionických hradel.

  3. Namapuj na qubitový prostor jako součást procesu transpilace.

Tento přístup omezení řeší tím, že znalosti o problému zůstávají ve fermionickém prostoru, kde optimalizační průchody mohou využít fermionickou strukturu a komutační relace ke snížení hloubky obvodu. Fermionický obvod popisuje, jaký výpočet provést, zatímco transpilace řeší, jak ho namapovat na qubity, což zajišťuje čistší oddělení zodpovědností.

Obecné indexování módů​

Modul operators i FermionicCircuit používají obecné indexování založené na módech, které nepředpokládá nic o povaze módů. Mód je pouze abstraktní index označující fermionický stupeň volnosti, bez vlastní sémantiky. Toto návrhové rozhodnutí odpovídá modulu operátorů a zajišťuje maximální flexibilitu. Například můžeš implementovat časový vývoj pro libovolný operátor implementující protokol OperatorTrait, bez ohledu na jeho matematickou reprezentaci.

Sestavení fermionického obvodu​

Příklad níže implementuje časový vývoj popsaný v předchozí části. Sestaví FermionicCircuit zadáním počtu fermionických módů a poté přidá fermionická hradla z qiskit_fermions.circuit.library, která časový vývoj implementují.

Příklad také ukazuje, jak do operátoru zahrnout znalosti o dané oblasti pomocí seskupování členů operátoru. Přiřazením indexů skupin členům hamiltoniánu zachováš strukturní informace, které mohou optimalizační průchody využít v celém transpilačním zásobníku.

>>> from qiskit_fermions.circuit import FermionicCircuit
>>> from qiskit_fermions.circuit.library import Evolution
>>> from qiskit_fermions.operators import FermionOperator, cre, ann
>>>
>>> # Create a circuit with 4 fermionic modes
>>> circuit = FermionicCircuit(4)
>>>
>>> # Define a simple fermionic Hamiltonian
>>> hamiltonian = FermionOperator.from_terms([
... ([cre(0), ann(2)], 0.5),
... ([cre(2), ann(0)], 0.5),
... ([cre(1), ann(3)], 0.5),
... ([cre(3), ann(1)], 0.5),
... ])
>>> # Add some problem structure by grouping our Hamiltonian terms
>>> hamiltonian.groups = [0, 0, 1, 1]
>>>
>>> # Add an evolution gate to implement exp(-i * t * H)
>>> evolution = Evolution(4, hamiltonian, time=1.0)
>>> circuit.append(evolution, circuit.register)

A simple `FermionicCircuit` with a single time evolution gate.

A decomposed `FermionicCircuit` with several time evolution gates.

Všimni si, že seskupení členů operátoru se zachovává i při jednoduchých operacích, jako je dekompozice. To ukazuje, jak strukturní informace procházejí zásobníkem obvodu. Úplnou transpilaci na qubity najdeš v průvodci Transpilace fermionických obvodů.

Oddělení hradel pomocí bariéry​

Optimalizační průchody slučují sousední hradla, kdykoli to jde. Například MergeOrbitalRotations spojí řadu po sobě jdoucích hradel OrbitalRotation do jednoho a MergeSlaterDeterminantPreparation zapracuje InitializeModes do rotace, která po něm následuje.

Použij FermionicCircuit.barrier(), když tomu chceš zabránit. Bariéra nemá žádný unitární účinek, takže nemění stav, který tvůj obvod připravuje; pouze označuje místo, přes které průchody hradla nesloučí. Zavolej ji bez argumentů, aby zahrnula všechny módy, nebo jí předej módy, na které ji chceš omezit:

>>> from qiskit_fermions.circuit.library import OrbitalRotation
>>> import numpy as np
>>>
>>> rotations = FermionicCircuit(4)
>>> rotations.append(OrbitalRotation(np.eye(4, dtype=complex)), rotations.register)
>>> rotations.barrier()
>>> rotations.append(OrbitalRotation(np.eye(4, dtype=complex)), rotations.register)

A `FermionicCircuit` with a barrier separating two orbital rotations.

Bariéry přežijí transpilaci z fermionů na qubity, takže omezují i následnou optimalizaci na úrovni qubitů. Tuto fázi popisuje průvodce Transpilace fermionických obvodů.

Opakování obvodu​

Mnoho algoritmů aplikuje stejný blok hradel mnohokrát. Typickým případem je časový vývoj: Trotterův krok se sestaví jednou a poté se opakuje, dokud se nedosáhne cílového času. Použij repeat() k sestavení opakovaného obvodu a compose() k jeho připojení k předponě s přípravou stavu.

Příklad níže sestavuje Trotterův krok druhého řádu pro Fermiho-Hubbardův model. Krok je symetrický: rozdělí člen přeskoku na dvě hradla OrbitalRotation s poloviční dobou trvání, která obklopují interakci na místě.

>>> import scipy.linalg
>>> from qiskit_fermions.circuit.library import InitializeModes, OrbitalRotation
>>>
>>> norb, reps, time = 2, 3, 1.0
>>> num_modes = 2 * norb
>>> dt = time / reps
>>>
>>> hopping = np.zeros((norb, norb))
>>> hopping[0, 1] = hopping[1, 0] = -1.0
>>> interaction = FermionOperator.from_dict(
... {(cre(p), ann(p), cre(p + norb), ann(p + norb)): 2.0 for p in range(norb)}
... )
>>>
>>> def rotation(duration):
... propagator = scipy.linalg.expm(-1j * duration * hopping)
... # the same rotation acts on the alpha and beta halves of the register
... return scipy.linalg.block_diag(propagator, propagator)
>>>
>>> trotter_step = FermionicCircuit(num_modes)
>>> trotter_step.append(OrbitalRotation(rotation(dt / 2)), trotter_step.modes)
>>> trotter_step.append(
... Evolution(num_modes, interaction, dt, atomic=True), trotter_step.modes
... )
>>> trotter_step.append(OrbitalRotation(rotation(dt / 2)), trotter_step.modes)

Opakováním kroku a jeho připojením k referenčnímu stavu Hartreeho-Focka získáš celý vývoj:

>>> evolution = FermionicCircuit(num_modes)
>>> evolution.append(InitializeModes([True, False, True, False]), evolution.modes)
>>> evolution.compose(trotter_step.repeat(reps), inplace=True)
>>> evolution.count_ops()["OrbitalRotation"]
6

A `FermionicCircuit` with repeated steps.

Opakování se rozbalí do vráceného obvodu, místo aby byla zabalena do jediného hradla, takže count_ops() napočítá dvě rotace na krok. Právě toto rozbalení činí redundanci na hranicích kroků viditelnou pro transpilátor: koncová rotace s poloviční dobou trvání jednoho kroku a úvodní rotace dalšího kroku spolu sousedí, takže je MergeOrbitalRotations spojí do jediné rotace.

>>> from qiskit_fermions.transpiler import FermionicPassManager
>>> from qiskit_fermions.transpiler.passes import MergeOrbitalRotations
>>>
>>> merged = FermionicPassManager([MergeOrbitalRotations()]).run(evolution)
>>> merged.count_ops()["OrbitalRotation"]
4

A `FermionicCircuit` with repeated steps and merged orbital rotations.

Výsledek stojí jednu rotaci na krok plus jednu, což je přesně to, co získáš ručním sloučením těchto polovičních kroků. Zapsání kroku v jeho přirozené symetrické podobě a jeho opakování vytvoří stejný obvod, takže sloučení se přenechá optimalizační fázi.

Když potřebuješ opakování udržet oddělená, předej insert_barriers=True, čímž mezi ně vložíš barrier(). Optimalizační průchody hradla přes bariéru nesloučí, takže každá rotace zůstane zachována:

>>> separated = trotter_step.repeat(reps, insert_barriers=True)
>>> FermionicPassManager([MergeOrbitalRotations()]).run(separated).count_ops()[
... "OrbitalRotation"
... ]
6

A `FermionicCircuit` with repeated steps separated by barriers.

Poznámka

Argument reps třídy FermionicSuzukiTrotter je odlišný koncept. Rozdělí jedno hradlo Evolution na více kratších činitelů, zatímco repeat() duplikuje celé obvody. Opakování obvodu, který obsahuje jediné Evolution, pouze znásobí jeho celkový čas vývoje.

Měření fermionických módů​

measure_all() přečte každý mód do vlastního klasického bitu, přičemž páruje mód i s bitem i. Použij measure() s vlastním ClassicalRegister, pokud chceš přečíst jen některé z nich.

>>> measured = trotter_step.measure_all(inplace=False)
>>> measured.count_ops()["measure"]
4

Předání inplace=False vrátí změřenou kopii a původní obvod ponechá beze změny, na čemž záleží, protože měření není unitární: obvod, který ho obsahuje, už nelze aplikovat na stavový vektor, takže si nech nezměřený obvod, pokud ho chceš také simulovat.

Měření zde, a ne na transpilovaném QuantumCircuit, zajišťuje, že vzorkované bitové řetězce zůstanou snadno čitelné. Fermionické měření pojmenovává mód, který čte, takže každá fáze, která módy přesouvá (RelabelModes na fermionické úrovni, rozložení a směrování na úrovni qubitů), přenáší měření s sebou, a bitový řetězec zůstává indexován podle módu, na který ses ptal.

Poznámka

Na rozdíl od measure_all() se před měření nevkládá žádná barrier(). Pokud ji tam chceš, zavolej barrier() nejdříve sám.

Zda změřený bit znamená to, co očekáváš, závisí na kódování fermionů na qubity, které se volí během transpilace, nikoli zde. Při kódování v okupační bázi, jako je Jordanovo-Wignerovo, je každý mód nesen jedním qubitem a bit je okupace tohoto módu; viz FermionicMeasure.

Transpilace fermionických obvodů​

Aby bylo možné implementovat kvantový algoritmus reprezentovaný tvým FermionicCircuit, musí být transpilován na QuantumCircuit. Jak na to, se dozvíš v průvodci Transpilace fermionických obvodů.

Další kroky​