Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Upper envelopes

DCEGM produces competing value branches and needs an upper-envelope configuration. Pass a typed configuration through DCEGM(envelope=...):

from lcm.solvers import DCEGM, LTMEnvelope

solver = DCEGM(savings_grid=..., envelope=LTMEnvelope())
ConfigurationContractMain controls
ExactEnvelopeCertified finite-candidate ownership using pylcm’s packaged native exact-affine kernelmax_runs
FUESEnvelopeFast upper-envelope scan approximationjump_thresh, n_points_to_scan
RFCEnvelopeRoof-cutting approximationjump_thresh, search_radius
LTMEnvelopeQuery-side line/segment evaluationnone

These four typed objects are the supported strategies. EnvelopeConfig is their union; string selectors are invalid.

pylcm no longer ships an MSS (HARK-style multi-segment scan) envelope: a timing study found it dominated by ExactEnvelope. An interface for envelopes maintained outside pylcm, which would let benchmark suites keep MSS, is planned in issue #632.

Exact envelope availability

The certified exact-affine read is forward-mode differentiable only. It carries a custom JVP, so jax.jvp and jax.jacfwd work and carry the exact slope, while jax.grad and jax.vjp raise: the rule inspects tangent finiteness so it can fail closed on a non-finite direction, which leaves JAX unable to transpose it, and no reverse rule is registered. This reaches ordinary models, because ExactEnvelope is the DCEGM default; NBEGM reaches it only with envelope_arithmetic="certified".

ExactEnvelope is the default. Its ownership decision relies on the exact-affine native payload installed as part of pylcm. pylcm neither downloads nor discovers an unrelated shared library at runtime.

A binary wheel contains the payload built for that wheel’s platform and toolchain. A source or editable install runs pylcm’s build hook locally: it builds the CPU library with the available C++ compiler and also builds the CUDA library when nvcc is available. A CPU payload does not provide a CUDA capability, and a payload built for a different platform, ABI, toolchain, or JAX backend is not interchangeable.

If the selected backend has no compatible loadable payload, model construction raises rather than falling back to ordinary floating-point comparisons. Reinstall pylcm in the target environment after supplying the required compiler; source-install details and the explicit no-kernel installation option are in Installation.

max_runs bounds supported envelope topology. The execution plan sizes the exact envelope’s independent node-cell loop through ENVELOPE_CELL_AXIS ("envelope_cell", exported by lcm.solvers). For example, Model(..., execution_config=ExecutionConfig(axis_widths={"envelope_cell": 3})) resolves three adjacent-candidate cells together. These are cells of the endogenous resource grid, distinct from the regime’s output-state cell axis. Width changes the working set while preserving candidate ownership and published quantities.

FUES uses a fixed scan unroll factor of one. This compiler choice is recorded in compilation identity and is not a field on FUESEnvelope. A model using only FUES has no envelope_cell loop and rejects that axis name.

Approximate backends

FUES, RFC, and LTM make different topology and execution trade-offs. FUES is scan-shaped; LTM evaluates candidate segments at query points and is usually more accelerator-friendly. Thresholds such as jump_thresh are algorithmic approximation parameters, not generic tolerances.

Switch backends only with model-specific validation:

The method background is in Discrete choice and upper envelopes and Scaling, memory, and hardware.