Model compatibility¶
A methodology needs things from the model. lma_labour_alignment needs the LMA add-on
and the LMA_trans extension switch; without them the alignment it performs on the
microdata has nothing to act on.
The engine does not complain about either. An unknown extension switch is dropped with a
console message, and an add-on that is not there simply is not applied. Left unchecked, both
simulations complete normally, produce identical output, and the scenario fails at the end
with NoEffectError — after paying for two full runs.
check_compatibility asks the question first.
from euromod_linking import check_compatibility
report = check_compatibility(system, "lma_labour_alignment")
print(report.ok)
for r in report.requirements:
print(f"{r.kind:10} {r.name:12} satisfied={r.satisfied} ({r.detail})")
True
addon LMA satisfied=True (present)
extension LMA_trans satisfied=True (accepted by this system)
The same check runs inside apply_scenario, including under validate_only=True, so a
scenario that cannot work is rejected before anything expensive happens. The report is on
the result under plan["compatibility"].
Reading a failure¶
Requirements are listed separately because they fail for different reasons and have different fixes.
lma_labour_alignment on BE/BE_2001: NOT ok
problem: lma_labour_alignment needs add-on system LMA_BE, but no system of the LMA
add-on applies to BE_2001.
note: This model looks like J2.54 (from folder-name), at or above the J2.54 floor
for lma_labour_alignment — so the release is not what is missing.
addon LMA satisfied=False (no add-on system LMA_BE applies to BE_2001)
extension LMA_trans satisfied=True (accepted by this system)
The extension is accepted, so the model is new enough; what is missing is an add-on system
covering this particular base system. Add-on applicability is per system, matched against
the add-on’s own AddOn_Applic patterns — an add-on can be installed and still not cover
older systems in the same country. Those two lines together say the fix is a different
system, not a different model.
A model that predates the extension entirely reads the other way round:
problem: lma_labour_alignment needs the LMA_trans extension, which BE/BE_2025 does not
accept. An unknown switch is silently ignored by the engine, so the run would
appear to succeed without applying it.
note: lma_labour_alignment needs EUROMOD release J2.54 or later; this model looks
like J2.19 (from folder-name).
Capability decides; the release explains¶
The two kinds of evidence are deliberately unequal.
Capability is authoritative. Whether the model ships an add-on is a directory listing, and whether a system accepts an extension switch is read from the model itself. Both are cheap and exact, and both are what actually determine whether a run will work.
The release is advisory. Which EUROMOD release a folder holds is not reliably knowable.
The documented marker XMLParam/Config/EuromodVersion.txt has writer code in the UI but
ships in no real release. The folder name is what the UI itself falls back to — and a user
who renames the folder erases it. So a detected release only ever improves the message; it
never blocks a run, and failing to detect one is not a failure.
model_release() tries, in order:
Source |
Note |
|---|---|
|
The documented contract. Authoritative when present — which, in practice, it is not. |
The model folder name |
|
|
Public releases only. |
|
The only marker in the model’s content, so it survives a rename — but the workbook runs to tens of megabytes, so it is opt-in via |
Releases sort by letter, then major, then minor, so J2.7 is older than J2.19 and
I6.0+ is older than J1.0. A trailing + marks a rolling build and sorts just above the
bare version, so J1.86+ is not read as older than J1.86. Anything unparseable compares
as None — “cannot compare”, never “too old”.
Three-valued by design¶
Every requirement is satisfied, unsatisfied, or undeterminable. Only the middle one
produces a problem; the third produces a note and leaves the report ok.
That distinction is the whole safety property. Collapsing “the model could not be read” into “the requirement is not met” would refuse to run against a perfectly good model, which is a worse failure than the late one this check replaces. If you never loaded a model at all, the check reports that it verified nothing and blocks nothing.
Set EUROMOD_SKIP_COMPAT_CHECK=1 to disable it entirely.
Surveying a model¶
compatibility_matrix answers “what can I actually run here” without writing a scenario:
from euromod import Model
from euromod_linking import compatibility_matrix
model = Model(r"C:\EUROMOD_RELEASES")
df = compatibility_matrix(model, "BE")
df[["system", "methodology", "ok", "model_release", "min_model_release"]]
system methodology ok model_release min_model_release
BE_2001 lma_labour_alignment False J2.54 J2.54
BE_2001 scale_variables True J2.54
BE_2019 lma_labour_alignment False J2.54 J2.54
BE_2019 scale_variables True J2.54
BE_2020 lma_labour_alignment True J2.54 J2.54
BE_2020 scale_variables True J2.54
BE_2025 lma_labour_alignment True J2.54 J2.54
BE_2025 scale_variables True J2.54
One model, one release, and the answer still differs by system — which is the point of asking per system rather than per model. Pass a country code unless you mean otherwise: walking every country of a full model means loading every country.
Declaring a floor¶
A methodology states its earliest supported release on its MethodSpec:
register(MethodSpec(
name="lma_labour_alignment",
...
addon_requirements=((("LMA", "LMA_{cc}"),), (("LMA_trans", True),)),
min_model_release="J2.54", # first internal release shipping the LMA_trans extension
))
{cc} in an add-on requirement is resolved against the scenario’s country, so
"LMA_{cc}" becomes LMA_BE and is checked against the add-on systems that actually apply
to the base system.