MonomialPropagator
Abstract base for the classical monomial-propagation simulators.
The propagation graph owns the gate information; evaluation methods
(:meth:expectation_value, :meth:gradient, ...) take only parameters.
Concrete subclasses implement :meth:__init__ (resolving their operator family to a
:class:~monoprop.majorana.MajoranaOperator and calling :meth:_init_simulator)
and :meth:_circuit_gates (validating the circuit's gate family).
.. note::
Incremental building and gate order. In the Heisenberg picture the
Heisenberg evolution applies gates back-to-front, so each
:meth:build_graph / :meth:propagate call consumes its gate
sequence in reverse. Splitting one circuit into forward chunks across several
calls is therefore not equivalent to a single call with the whole sequence:
the chunks are each reversed but not globally reordered. In the Schrodinger
picture gates are applied front-to-back, so a forward split is equivalent.
When you need incremental building to reproduce a single-call result, use the
Schrodinger picture (or pass the full sequence in one call).
Attributes
attributen_parametersintNumber of distinct variational parameters seen while building the graph.
attributen_gatesintNumber of authoring gates ingested into the graph.
A single-term gate expands to one graph layer; a multi-term gate expands to several
layers sharing one gate, so n_gates \<= graph_layers. Stays correct after a graph
prefix is consumed by :meth:contract_partially / :meth:propagate.
attributeparameter_mappinglist[int]The parameter mapping owned by the graph, one entry per graph layer.
Entry i is the variational-parameter index driving the i-th graph layer (a
generated Majorana monomial), in the same order as the parameter vector passed to
:meth:expectation_value. This is the graph's native (per-monomial) mapping, which
is finer-grained than the per-gate mapping of the authoring
:class:~monoprop.circuit.Circuit when gates bundle several monomials.
attributenum_modesintNumber of fermionic modes for the simulator.
attributegraph_layersintNumber of evolved Majoranas (graph layers).
attributeschrodingerboolWhether the simulator is in the Schrodinger picture (else Heisenberg).
attributecutoffintCurrent cutoff value for the simulation.
attributelower_atolNone | floatCurrent lower absolute tolerance for the cutoff function (None if unset).
attributeupper_atolNone | floatCurrent upper absolute tolerance for the cutoff function (None if unset).
attributecutoff_typestrCurrent cutoff type ("length" or "support").
Read-only on the base; :class:~monoprop.majorana_propagator.MajoranaPropagator
exposes a setter since either scheme is valid there.
Functions
funcfrom_circuit(cls, circuit, initial_operator, **config) -> SelfConstruct a propagator from a circuit and propagate it in one step.
Uses circuit.initial_state as the reference state and evolves circuit in
place via :meth:propagate -- a one-shot contraction that stores no graph. The
observable (initial_operator) and truncation settings (cutoff and the rest of
config) are supplied separately -- they are not part of the circuit.
Read the result off the evolved operator/state with :meth:evolved_operator (or
:meth:expectation_value) taking no parameters -- the circuit's angles are already
applied. This is the memory-lean path for a single evaluation; if you instead need a
reusable graph to re-evaluate at many angles (or to take gradients), construct the
propagator directly and call :meth:build_graph.
paramclsparamcircuitCircuitThe circuit whose gates and initial state define the evolution.
paraminitial_operatorobjectThe observable to propagate.
paramconfigobject= {}Returns
typing.SelfA propagator with circuit already evolved into its state (no graph stored).
funcbuild_graph(self, circuit, *, seed_parameters=None, only_rotate_len_k=0) -> NoneAppend a circuit to the propagation graph.
Builds (or extends) the reusable evolution graph, recording each layer's gate
information (the parameter that drives it and its generator coefficient) so that
later evaluation takes only parameters. The circuit's angle indices are local
(0-based); when extending a non-empty graph they are shifted up onto the
accumulated parameter axis automatically, so each call's circuit is authored
independently.
paramselfparamcircuitCircuitGates to append, as a :class:~monoprop.circuit.Circuit.
paramseed_parametersParameterValues= NoneThe full parameter vector covering the whole accumulated graph, used to regenerate the coefficient seed (by contracting the existing graph) so coefficient truncation sees realistic coefficients when extending. Only needed when extending a non-empty graph with coefficient-informed truncation; on the first (or a single) call it defaults to the circuit's own parameters. When omitted while extending, the new layers are built structurally (coefficient truncation is skipped for them); the engine validates the length of an explicit seed.
paramonly_rotate_len_kint= 0If > 0, apply gates to monomials of length <= k in the evolved operator even if they anticommute. Useful when many free-fermionic gates (generators that are length-2 Majorana monomials) are applied before expectation-value estimation in Schrodinger-picture simulations.
Returns
Nonefuncpropagate(self, circuit, *, only_rotate_len_k=0) -> NoneEvolve and contract immediately, without storing a graph.
More memory-efficient than :meth:build_graph because it does not retain
the propagation graph; use it for a single contraction at the circuit's parameters
rather than repeated re-evaluation.
paramselfparamcircuitCircuitGates to apply and the angle values to apply them at, as a
:class:~monoprop.circuit.Circuit.
paramonly_rotate_len_kint= 0See :meth:build_graph.
Returns
Nonefuncexpectation_value(self, parameters=None) -> floatCompute the expectation value at parameters.
Replays the stored graph against the current initial operator and reference state. This is a convenience wrapper that builds and immediately evaluates an expectation-value functional with no paring.
paramselfparamparametersParameterValues= NoneVariational parameter values, as a sequence in parameter-index
order, or a :class:~monoprop.circuit.Circuit (its parameters are used).
None evaluates the current operator with an empty parameter vector.
Returns
floatThe expectation value as a float.
funcexpectation_value_and_gradient(self, parameters=None) -> tuple[float, np.ndarray]Compute the expectation value and gradient at parameters.
Both quantities are computed in a single backward pass over the graph.
paramselfparamparametersParameterValues= NoneVariational parameter values (see :meth:expectation_value).
Returns
floatA tuple (expectation_value, gradient), where gradient is a NumPy
funcgradient(self, parameters=None) -> np.ndarrayCompute the gradient at parameters.
Note
Internally calls :meth:expectation_value_and_gradient and returns only its
gradient component.
paramselfparamparametersParameterValues= NoneVariational parameter values (see :meth:expectation_value).
Returns
numpy.ndarrayThe gradient as a NumPy array of float64 values, in canonical
funcexpectation_value_functional(self, pare_threshold=None) -> Callable[..., float]Return a reusable callable computing the expectation value from parameters.
Returns a callable that accepts a parameter vector (a sequence, or None) and
returns the expectation value, replaying the current evolution graph. Build it once
and call it repeatedly across many parameter values.
paramselfparampare_thresholdfloat | None= NoneEdge-retention cutoff for a masked execution plan built for
this functional: edges whose contribution falls below the threshold are
pared away so they are skipped during replay (a speed-up for sparse
graphs, at the cost of some memory and accuracy). None (the default)
disables paring.
Returns
collections.abc.CallableA callable fn(parameters=None) -> float.
funcexpectation_value_and_gradient_functional(self, pare_threshold=None) -> Callable[..., tuple]Return a reusable callable computing (expectation value, gradient).
Like :meth:expectation_value_functional, but the returned callable computes
both the expectation value and the full parameter gradient in a single backward
pass over the graph.
paramselfparampare_thresholdfloat | None= NoneSee :meth:expectation_value_functional.
Returns
collections.abc.CallableA callable fn(parameters=None) -> (float, np.ndarray), where the
funccontract_partially(self, parameters=None, *, inplace=True) -> np.ndarrayContract the graph into the operator/state at parameters.
Permanently folds the stored gates, evaluated at parameters, into the
operand: the initial operator in the Heisenberg picture, or the reference state
in the Schrodinger picture. This shrinks the graph that remains to be replayed,
which is useful when a prefix of the circuit is fixed and its contribution can
be baked in once instead of being replayed on every evaluation.
paramselfparamparametersParameterValues= NoneVariational parameter values (see :meth:expectation_value).
paraminplacebool= TrueIf True (default), update the internal state, consuming the
graph. If False, leave the stored graph untouched and only return
the contracted coefficients, so the same graph can be reused with other
parameters.
Returns
numpy.ndarrayThe evolved coefficients (core term excluded) as a NumPy array. In the
funcevolved_operator(self, parameters=None, *, atol=1e-12) -> dict[tuple[int, ...], complex]Return the evolved operator/state as a dict, without modifying state.
Equivalent to :meth:contract_partially with inplace=False, returned as a
mapping keyed by Majorana indices and without touching the simulator state.
paramselfparamparametersParameterValues= NoneVariational parameter values (see :meth:expectation_value).
paramatolfloat= 1e-12Absolute tolerance for filtering small coefficients; terms with
|coeff| \< atol are dropped. Defaults to 1e-12; set to 0.0 to
keep all terms.
Returns
dictThe evolved operator (Heisenberg picture) or the evolved state (Schrodinger
funcupdate_initial_operator(self, new_operator) -> NoneReplace coefficients of the initial operator (existing terms only).
Re-weights the initial operator the graph is evaluated against, without touching the evolution graph or rebuilding the simulator. Only the initial operator is affected -- the gates and their generator coefficients are unchanged -- and only Majorana terms already present in the initial operator can be updated (no new terms are introduced).
paramselfparamnew_operatordict[tuple[int, ...], complex]Mapping from Majorana-index tuples to their new complex coefficients.
Returns
Nonefuncsize(self) -> intNumber of Majorana terms currently tracked.
paramselfReturns
intThe number of distinct Majorana monomial terms in the simulator's current
funcgraph_size(self) -> tuple[int, int]Size metrics of the evolution graph.
paramselfReturns
intA tuple (n_cos_indices, n_cycles): the number of cosine indices and the