FermionicCircuit¶
- class FermionicCircuit(num_modes)¶
Bases:
objectA wrapper around
QuantumCircuitfor expressing fermionic circuits.This class maintains a reduced API compared to the full API of the underlying
QuantumCircuit. This is done to avoid exposing (among other methods) the ability to apply qubit-based gates onto a fermionic circuit, which would not be a well-defined operation in the general case.barrier()is re-exposed because it is an exception to that rule: a barrier acts on modes without interpreting them and carries no unitary content, so it is as well-defined on a fermionic register as it is on a qubit one.Measurements are likewise available, via
measure()andmeasure_all(). They are the one non-unitary operation this circuit carries, so they are reached through those methods rather than throughappend(), which stays restricted to unitary gates. Whether the resulting bit is meaningful depends on the fermion-to-qubit encoding chosen later, during transpilation, rather than on this circuit (seeFermionicMeasure).Initializing a circuit instance can be done with the arguments listed below.
- Parameters:
num_modes (int) – the number of fermionic modes on which this circuit acts.
Attributes
- modes¶
The fermionic mode
bitsthat this circuit acts upon.
- register: FermionicRegister¶
The inner circuit’s
FermionicRegister.
Methods
- add_register(*cregs)¶
Adds classical registers to this circuit.
Only classical registers can be added: the fermionic mode register is fixed at construction and is available as
register.- Parameters:
cregs (ClassicalRegister) – the classical registers to add.
- Raises:
ValueError – if any of the provided registers is not a
ClassicalRegister.- Return type:
None
- append(gate, fargs, cargs=None, *, copy=True)¶
Appends a
FermionicGateto this circuit.- Parameters:
gate (FermionicGate) – the fermionic gate to apply.
fargs (Qubit | QuantumRegister | int | slice | Sequence[Qubit | int]) – the fermionic modes on which this gate acts.
cargs (None) –
the classical bits on which this gate acts.
Warning
No gates of this kind are currently supported. A
FermionicGateis unitary and so takes no classical bits; usemeasure()to add the one instruction that does.
- Raises:
ValueError – if the provided
gateis not an instance ofFermionicGate.- Return type:
None
- barrier(*fargs, label=None)¶
Re-exposes
barrier().A barrier carries no unitary effect. It marks a synchronization point that the optimization passes will not fuse gates across, which is how you keep a pass such as
MergeOrbitalRotationsorMergeSlaterDeterminantPreparationfrom combining the gates on either side of it.
- compose(other, fargs=None, *, front=False, inplace=False)¶
Composes another
FermionicCircuitonto this one.The instructions of
otherare inlined into this circuit, rather than wrapped into a single gate. This mirrorscompose()with its defaultwrap=False. Thewrap=Truecounterpart is deliberately not offered: a dedicated encapsulation mechanism is planned instead, so adding a second way to box up a block of instructions here would leave two patterns solving the same problem.- Parameters:
other (FermionicCircuit) – the circuit to compose onto this one. It may act on fewer modes than this circuit, in which case
fargsselects the modes it is placed on.fargs (Qubit | QuantumRegister | int | slice | Sequence[Qubit | int] | None) – the fermionic modes of this circuit onto which
otheris placed. Defaults to all of this circuit’s modes, in order.front (bool) – whether to compose
otherbefore rather than after this circuit’s instructions.inplace (bool) – whether to modify this circuit rather than return a new one.
- Returns:
The composed circuit, or
Noneifinplaceis set.- Raises:
ValueError – if
otheris not an instance ofFermionicCircuit. Only fermionic circuits are accepted because the plaincompose()would happily inline qubit-based instructions, bypassing the type guard thatappend()enforces.CircuitError – if
otheracts on more modes than this circuit, orfargsdoes not match its width.
- Return type:
FermionicCircuit | None
- count_ops()¶
Re-exposes
count_ops().- Return type:
- decompose(gates_to_decompose=None, reps=1)¶
Re-exposes
decompose().- Parameters:
gates_to_decompose (str | type[Instruction] | Sequence[str | type[Instruction]] | None)
reps (int)
- Return type:
- measure(fargs, cargs)¶
Measures the given fermionic modes into the given classical bits.
This appends one
FermionicMeasureper mode. The classical bits must already exist; add them withadd_register(), or usemeasure_all(), which creates a register for you.The pairing of modes to classical bits is yours, and it is preserved through transpilation: the mode a measurement acts on is permuted by a pass such as
RelabelModes, but the classical bit it writes into is not.- Parameters:
fargs (FermionicSpecifier) – the fermionic modes to measure.
cargs (ClbitSpecifier) – the classical bits to write the outcomes into.
- Raises:
CircuitError – if the number of modes and classical bits differ, or if a specifier does not resolve against this circuit.
- Return type:
None
- measure_all(*, add_bits=True, inplace=True)¶
Measures every mode of this circuit, in order, into one classical bit each.
Mode
iis measured into classical biti, so a sampled bitstring is indexed by mode.Note
Unlike
measure_all(), this inserts nobarrier()before the measurements. Callbarrier()yourself beforehand if you want one there.- Parameters:
add_bits (bool) – whether to add a new
measClassicalRegistersized to this circuit’s modes. When this isFalse, the existing classical bits are used instead, and calling this method again simply measures into them a second time.inplace (bool) – whether to modify this circuit rather than return a new one.
- Returns:
The measured circuit, or
Noneifinplaceis set.- Raises:
CircuitError – if
add_bitsis set and this circuit already carries a register namedmeas(which is what a secondmeasure_all()call runs into). Passadd_bits=Falseto measure into the existing bits instead.ValueError – if
add_bitsis not set and this circuit has fewer classical bits than modes.
- Return type:
FermionicCircuit | None
- repeat(reps, *, insert_barriers=False)¶
Repeats this circuit
repstimes.The repetitions are flattened: the returned circuit holds this circuit’s instructions
repstimes in sequence, rather than one gate wrapping the circuit asrepeat()produces. As a consequencecount_ops()scales withreps, anddecompose()decomposes the repeated body rather than peeling off a repetition.Flattening also leaves the gates that meet at a repetition boundary adjacent, so the optimization passes can fuse them. Set
insert_barriersto keep the repetitions apart instead, which places abarrier()that those passes do not fuse across.Note
This is unrelated to the
repsargument ofFermionicSuzukiTrotter, which subdivides a singleEvolutioninto more, shorter factors. Repeating a circuit holding oneEvolutionmerely multiplies its total evolution time.See also
Work with fermionic circuits works through a repeated Trotter step, including the boundary fusion and how to prevent it.
- Parameters:
reps (int) – how often this circuit should be repeated. Repeating it zero times yields an empty circuit, which is the identity.
insert_barriers (bool) – whether to place a
barrier()between consecutive repetitions. No barrier is placed after the final repetition, so the returned circuit ends on the same instruction it would without this argument.
- Returns:
A new circuit containing
repsrepetitions of this circuit.- Raises:
ValueError – if
repsis negative.- Return type:
Protocol Methods
- _apply_unitary_(vec, norb, nelec, copy)¶
Applies this circuit to an ffsim state vector, implementing ffsim’s protocol.
This walks the circuit in topological order and applies each instruction’s unitary effect to the state vector via ffsim’s
ffsim.SupportsApplyUnitaryprotocol. Each instruction acting on a subset of the register has its fermionic modes relabeled to their absolute (global) indices before being applied.See
_apply_unitary_placed_()for the details; this method assumes the circuit’s modes are the vector’s modes0..num_modes(i.e. an identity mode placement).- Parameters:
vec (ndarray) – the state vector to apply this circuit to. An empty circuit returns it unchanged.
norb (int) – the number of spatial orbitals.
nelec (int | tuple[int, int]) – either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.
copy (bool) – whether to copy the vector before operating on it.
- Returns:
The transformed vector.
- Raises:
TypeError – if a circuit instruction other than a
Barrierdoes not implement ffsim’sffsim.SupportsApplyUnitaryprotocol.ValueError – if a circuit instruction declines to apply its unitary for the given
norbandnelec; or if an instruction implementing only the plain_apply_unitary_protocol is placed on a non-identity mode subset.
- Return type:
- _apply_unitary_placed_(vec, norb, nelec, copy, freg_indices)¶
Applies this circuit after placing its modes onto the vector’s global modes.
This walks the circuit in topological order and applies each instruction’s unitary effect to the state vector via ffsim’s
ffsim.SupportsApplyUnitaryprotocol. Each instruction’s own modes are first mapped through this circuit’s placement: a circuit-local modemmaps to the global modefreg_indices[m], so a sub-instruction acting on circuit-local modes[m0, m1, ...]is applied on the global modes[freg_indices[m0], freg_indices[m1], ...]. With the identity placementfreg_indices == 0..num_modesthis is exactly_apply_unitary_(); a subset placement lets this circuit act as the definition of a gate placed on a subset of a larger register (e.g.UCJ). This placement-aware extension is documented asSupportsApplyUnitaryPlaced– a package-specific protocol with no ffsim equivalent.An instruction is placed onto its absolute modes only if it implements the placement-aware
_apply_unitary_placed_extension (SupportsApplyUnitaryPlaced). An instruction implementing only ffsim’s plain_apply_unitary_– which has no mode argument and therefore acts on modes0..kof the vector – can only be honored when its placement is the identity[0, 1, ..., k-1]; on any other subset the placement cannot be expressed and the instruction is rejected rather than silently applied on the wrong modes.A
Barrieris skipped: it carries no unitary effect, so it constrains transpilation without contributing to the state vector.- Parameters:
vec (ndarray) – the state vector to apply this circuit to. An empty circuit returns it unchanged.
norb (int) – the number of spatial orbitals of the global state vector.
nelec (int | tuple[int, int]) – either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.
copy (bool) – whether to copy the vector before operating on it.
freg_indices (list[int]) – the absolute (global) mode indices that this circuit’s modes map onto.
- Returns:
The transformed vector.
- Raises:
TypeError – if a circuit instruction other than a
Barrierdoes not implement ffsim’sffsim.SupportsApplyUnitaryprotocol.ValueError – if a circuit instruction declines to apply its unitary for the given
norbandnelec; or if an instruction implementing only the plain_apply_unitary_protocol is placed on a non-identity mode subset.
- Return type: