RelabelModes¶
- class RelabelModes(permutation=None, *, solver=None, **kwargs)¶
Bases:
GenericPass[DAGCircuit,DAGCircuit]A transpilation pass to relabel the fermionic modes.
This pass reorders the fermionic modes of a circuit. The reordering is described by a
permutationlist, read as a mapping from original to new mode index: original modeiis placed at new indexpermutation[i]in the relabeled circuit. For example,permutation = [0, 2, 4, 1, 3, 5]places original mode1at new index2, original mode2at new index4, and so on. Being a permutation, each index must appear exactly once.Post-processing
The relabeling reorders the fermionic modes, which in turn influences the fermion-to-qubit mapping chosen by a later synthesis stage (and thus the achievable circuit depth). Because the mode order changes, any bitstring sampled from the final circuit is expressed in the new mode order and must be mapped back to the original order before it can be interpreted. The relabeling that was actually applied is recorded in a
permutationfield of the returnedFermionicDAGCircuit’smetadata.Important
Always read the relabeling from the circuit metadata rather than from
permutation. When the automatic optimization is used (i.e.permutationisNone), the applied permutation is only available from the metadata; and even whenpermutationwas provided explicitly, the metadata is guaranteed to reflect what the pass did.Note that the
permutationmetadata field is only present when the pass actually relabeled the circuit. When the pass has no effect – for example, when the automatic optimization cannot run because the optionalpyomodependency or asolveris missing – the returned circuit is unchanged and carries nopermutationmetadata, so access it defensively (e.g.qcirc.metadata.get("permutation")).Conceptually, undoing the relabeling assigns to each original mode
mthe value that was measured for new modepermutation[m]. In practice this is complicated by the fact thatFermionicRegistermodes and Qiskit’s classical bits run in opposite (little-endian) order, so the mode-space gather turns into an index negation (~idx) followed by a final reversal ([::-1]) on the counts bitstrings.The example below relabels a six-mode system from a blocked spin ordering (
[u0, u1, u2, d0, d1, d2]) to an interleaved one ([u0, d0, u1, d1, u2, d2]), a common trick to reduce the implementation depth, and then undoes the relabeling on the sampled counts:>>> from qiskit.passmanager import MultiStagePassManager >>> from qiskit.providers.basic_provider import BasicSimulator >>> from qiskit_fermions.circuit import FermionicCircuit >>> from qiskit_fermions.circuit.library import InitializeModes >>> from qiskit_fermions.transpiler import FermionicCircuitToDAG, QuantumDAGToCircuit >>> from qiskit_fermions.transpiler.passes import ( ... F2QSynthesis, F2QSynthesisPluginManager, RelabelModes, TrivialF2QLayout, ... ) >>> >>> # blocked occupation: spin-up orbitals 0 and 1 and spin-down orbital 0 are occupied >>> circ = FermionicCircuit(6) >>> circ.append(InitializeModes([1, 1, 0, 1, 0, 0]), circ.modes) >>> >>> synth_plugins = F2QSynthesisPluginManager() >>> synth = F2QSynthesis() >>> synth.methods["InitializeModes"] = synth_plugins.method("InitializeModes", "TrivialOccupation")() >>> >>> # map blocked mode order onto the interleaved one >>> relabel = RelabelModes(permutation=[0, 2, 4, 1, 3, 5]) >>> >>> pm = MultiStagePassManager( ... init=FermionicCircuitToDAG(), ... optimization=relabel, ... layout=TrivialF2QLayout(), ... synthesis=synth, ... output=QuantumDAGToCircuit(), ... ) >>> >>> qcirc = pm.run(circ) >>> qcirc.measure_all() >>> >>> bit_permutation = qcirc.metadata.get("permutation") >>> print(bit_permutation) [0, 2, 4, 1, 3, 5] >>> >>> res = BasicSimulator().run(qcirc, shots=1).result() >>> counts = res.get_counts() >>> print(counts) # measured in the interleaved ordering {'000111': 1} >>> >>> # undo the relabeling to recover the counts in the original blocked ordering >>> post_processed = { ... "".join(bitstring[~idx] for idx in bit_permutation)[::-1]: count ... for bitstring, count in counts.items() ... } >>> print(post_processed) # recovered in the original blocked ordering {'001011': 1}
Initializing this transpiler pass can be done with the arguments listed below.
- Parameters:
permutation (list[int] | None) – the index permutation used to relabel the fermionic mode indices. When this is
None, a permutation will be determined automatically based onbuild_excitation_span_minimization_model(). See alsopermutationfor more details.solver (pyomo.opt.SolverFactory | None) – the optimization problem solver instance used to solve the
build_excitation_span_minimization_model()problem. When this isNone, nopermutationcan be determined automatically. See alsosolverfor more details.kwargs – any additional keyword arguments will be forward to
build_excitation_span_minimization_model().
Attributes
- permutation¶
The index permutation used to relabel the fermionic mode indices.
This may either be a
list[int], mapping original mode indexito new mode indexpermutation[i](see the class docstring for details). Its length has to match the number of fermionic modes of the circuit being transpiled, and each index has to appear exactly once. This scenario therefore requires the transpiler pass to be tailored quite specifically to the user’s circuit.Or it may be
None, in which case thebuild_excitation_span_minimization_model()function is used to define an optimization problem which tries to minimize the span of all occurring fermionic excitations. In this case the applied permutation is only available from the transpiled circuit’s metadata (see the class docstring).Note
The use of this optimization model is only implemented for time evolution gates containing a
FermionOperatorinstance.
- solver¶
The optimization problem solver instance to automatically find
permutation.When
permutationisNone, the optimization problem defined bybuild_excitation_span_minimization_model()is used to automatically find a good permutation of mode indices. In such a case, the user must provide an optimizer to solve this model.
Methods
- find_permutation(dag)¶
Finds a mode index
permutationwhen not specified by the user.This function only gets called when
permutationis not specified by the user (i.e. it isNone). When that is the case, it does the following:ensure that the optional pyomo dependency is installed. Otherwise, no optimization can be performed and this transpiler pass has no effect.
ensure that a
solveris specified. Otherwise, no optimization can be performed and this transpiler pass has no effect.gather all the fermionic excitations from any
Evolutiongates containing aFermionOperatorinstance.build the optimization problem using
build_excitation_span_minimization_model(), forwarding any additional keyword arguments (kwargs) from when this transpiler pass was constructed.solve the optimization problem using
solverand extract the final permutation.
- Parameters:
dag (FermionicDAGCircuit) – the circuit to be transpiled.
- Returns:
The permutation to use. When
None, this transpiler pass will have no effect.- Raises:
NotImplementedError – when encountering an
Evolutiongate containing an operator that is not aFermionOperatorinstance.- Return type:
tuple[list[int] | None, pyomo.opt.results.results_.SolverResults | None]
- run(dag)¶
Runs this transpilation pass.
- Parameters:
dag (DAGCircuit) – the input circuit with fermion-based instructions. Only
DAGOpNodewithFermionicGateinstances as theiropare supported.- Returns:
The output circuit which is still acting on a fermionic register.
- Raises:
NotImplementedError – when the provided input circuit has more than a single register.
- Return type:
Inherited Methods
- execute(passmanager_ir, state, callback=None)¶
Execute optimization task for input Qiskit IR.
- Parameters:
passmanager_ir (IR) – Qiskit IR to optimize.
state (PassManagerState) – State associated with workflow execution by the pass manager itself.
callback (Callable[[Task, IR_OUT, PropertySet, float, int], None] | None) – A callback function which is called per execution of optimization task.
- Returns:
Optimized Qiskit IR and state of the workflow.
- Return type:
tuple[IR_OUT, PassManagerState]
- update_status(state, run_state)¶
Update workflow status.
- Parameters:
state (PassManagerState) – Pass manager state to update.
run_state (RunState) – Completion status of current task.
- Returns:
Updated pass manager state.
- Return type: