Initialisation and updates
Constructing the simulator, choosing the Heisenberg or Schrödinger picture, and updating the operator in place.
The top-level classes are MajoranaPropagator and PauliPropagator (Python) /
MonomialPropagator<NumModes> (C++). Every significant aspect of the
simulation can be tuned at construction time and updated at runtime without
rebuilding. The structural and coefficient cutoffs are covered separately in
Truncation and cutoffs.
Heisenberg and Schrödinger pictures
Pass schrodinger_cutoff to switch from the default Heisenberg picture
(operator evolution) to the Schrödinger picture (density matrix evolution). In the
Schrödinger picture gates are applied to the state, whereas in the Heisenberg
picture they are applied to the observable.
schrodinger_cutoff is the truncation applied to the initial state. It must be
set higher than the regular cutoff for the Schrödinger-picture result to
match the Heisenberg-picture one: under length truncation the two pictures agree
on fermionic circuits when schrodinger_cutoff = cutoff + 2
(see Appendix of (Chakraborty et al., 2026)).
Operator updates
The coefficients of the initial operator can be patched after construction without rebuilding the simulator or the graph. The keys are Majorana monomials (tuples of indices); the values are the new coefficients, which must keep each monomial Hermitian (real for length-4 terms, imaginary for length-2 — see the Notation page):
from monoprop import MajoranaPropagator, MajoranaOperator
observable = MajoranaOperator({(0, 1, 2, 3): 1.0}, 4)
sim = MajoranaPropagator(observable, initial_state=[0, 1], cutoff=4)
sim.update_initial_operator({(0, 1, 2, 3): 0.5})This lets you estimate several observables without re-propagating: in the Schrödinger picture the state is evolved independently, so you can re-weight the observable and read it off against the same evolved state; in the Heisenberg picture the same graph can be reused with different initial operators.
Only terms that already exist in the initial operator can be updated; supplying a
monomial that is not present (or a non-Hermitian coefficient) raises
RuntimeError:
import pytest
from monoprop import MajoranaPropagator, MajoranaOperator
observable = MajoranaOperator({(0, 1, 2, 3): 1.0}, 4)
sim = MajoranaPropagator(observable, initial_state=[0, 1], cutoff=4)
with pytest.raises(RuntimeError):
sim.update_initial_operator({(1, 2, 3, 4): 0.5}) # This monomial doesn't exist