Every quantum chemistry pipeline hits the same translation problem before a single gate runs: electrons are fermions, qubits are not, and the two don't behave the same way under exchange. A fermion-to-qubit mapper is the piece of the pipeline that solves this, and which mapper you pick changes qubit count, gate locality, and how much classical pre-processing happens before touching a circuit at all. Qiskit Nature (version 0.8) ships several.
Why fermions need special handling
Swap two electrons and the wavefunction picks up a minus sign, the antisymmetry that underlies the Pauli exclusion principle. Qubits don't do that automatically: swapping two qubits in a circuit doesn't introduce a sign flip on its own. A mapper has to encode that antisymmetry explicitly into how fermionic creation and annihilation operators translate into Pauli operators (X, Y, Z) acting on qubits, which is a nontrivial translation, not a relabeling.
Jordan-Wigner: the direct mapping
from qiskit_nature.second_q.mappers import JordanWignerMapper
mapper = JordanWignerMapper()
Jordan-Wigner is the most literal mapping: one spin-orbital maps to exactly one qubit, and the occupation of that orbital (occupied or empty) maps directly to that qubit's |1⟩ or |0⟩ state. That directness makes it the easiest mapping to reason about and debug. Its cost is locality: encoding the required antisymmetry means a fermionic operator on one orbital turns into a Pauli string spanning every qubit up to that orbital's index in the ordering, a chain of Z operators called a Jordan-Wigner string. Operators that would be local in the fermionic picture become non-local in the qubit picture, which matters directly for circuit depth on real hardware, since non-local Pauli strings need more gates to implement one way or another.
Parity: trading locality for a qubit reduction
from qiskit_nature.second_q.mappers import ParityMapper
mapper = ParityMapper(num_particles=problem.num_particles)
The parity mapping stores information differently: instead of one qubit per orbital tracking occupation directly, it encodes parity (even or odd electron count) locally on each qubit, while occupation information becomes spread across all of them. The payoff shows up when you also know the total particle number ahead of time, a physically reasonable thing to know for a fixed molecule, since passing num_particles lets the mapper drop two qubits that become redundant once electron-number conservation is accounted for. For a small system, two fewer qubits is a meaningful fraction of the total.
Bravyi-Kitaev: splitting the difference
Jordan-Wigner keeps occupation information local but pays for it with non-local operators. Parity does the reverse. Bravyi-Kitaev sits between the two, using a tree-based encoding where both occupation and parity information are partially local, so operators typically act on O(log n) qubits instead of either the fully local (Jordan-Wigner occupation) or fully spread-out (Parity occupation) extremes. It's available in Qiskit Nature alongside the other two, and it's worth reaching for specifically when circuit depth from long Pauli strings is the bottleneck rather than raw qubit count.
Squeezing further: tapering with symmetries
from qiskit_nature.second_q.mappers import TaperedQubitMapper
tapered_mapper = problem.get_tapered_mapper(mapper)
Beyond the choice of base mapping, a molecule's Hamiltonian often has Z2 symmetries, structural redundancies in how the problem was encoded, that a TaperedQubitMapper identifies and removes entirely. For H₂ in a minimal basis, mapped with Parity and combined with tapering, the qubit count is reducible all the way down to a single qubit, a dramatic illustration that "how many qubits does this molecule need" depends heavily on encoding choices, not only on the molecule's inherent physical complexity.
Qubit ordering matters too
from qiskit_nature.second_q.mappers import InterleavedQubitMapper
interleaved = InterleavedQubitMapper(mapper)
Separately from which mapper you pick, InterleavedQubitMapper changes how spin-up and spin-down orbitals are arranged relative to each other, interleaved rather than the default block ordering (all spin-up orbitals, then all spin-down). Ordering doesn't change the physics, but it changes which operators end up acting on adjacent qubits, which affects how well a mapped Hamiltonian matches real hardware's connectivity graph.
The practical decision
For learning the pipeline or debugging a new problem, Jordan-Wigner's directness makes mistakes easiest to spot. Once you're optimizing for a real qubit budget or targeting real hardware with limited connectivity, Parity with particle-number reduction (and tapering, if the symmetries are there to exploit) is usually the better default, with Bravyi-Kitaev worth benchmarking specifically when circuit depth, not qubit count, is the binding constraint. None of these choices change the underlying chemistry. They change how expensive that chemistry is to represent on a real device, which is exactly why molecule simulation needs so many qubits in the first place, and why the mapper is a real design decision rather than boilerplate.
Try this next
- Build the same H₂ Hamiltonian with
JordanWignerMapperandParityMapper(num_particles=problem.num_particles)and comparemapper.map(problem.hamiltonian.second_q_op()).num_qubitsbetween them directly. - Apply
TaperedQubitMapperon top of Parity for H₂ and confirm the qubit count drops to one, then check whetherGroundStateEigensolverstill returns the same ground-state energy as the untapered version. - Read our molecule ground-state solver walkthrough to see a mapper plugged into a full VQE pipeline rather than examined in isolation.