Skip to content

mdl: reader keeps 3 more SIR.mdl connectors than xmutil #512

Closed

Description

@bpowers

test_mdl_equivalence compared our MDL reader against xmutil on src/libsimlin/testdata/SIR.mdl and failed: we produced 16 connectors in the diagram, xmutil 13.

The 3 extra connectors are arrows drawn into the stock Susceptible Population S from the variables its initial value uses.
xmutil drops every connector that ends at a stock (XMILEGenerator.cpp, meant for flow pipes); our reader drops only flow pipes.
Ours is right: the arrows are in the sketch, and XMILE puts no restriction on a <connector>'s target (docs/reference/xmile-v1.0.html).

Status on main

xmutil, the xmutil feature and tests/mdl_equivalence.rs were deleted in #1080 (ea8367a).
The reader's checks are now Vensim's own output in test/, so nothing remains to fix here.

Activity

  1. bpowers commented on May 16, 2026

    @bpowers
    OwnerAuthor

    Related: #570 -- same class (an xmutil-feature-gated tests/mdl_equivalence.rs assertion that is not exercised by the binding pre-commit/CI cargo test), distinct instance. #512 is a pre-existing-on-main divergence in the view/sketch connector parser (src/simlin-engine/src/mdl/view/) on SIR.mdl in the non-ignored test_mdl_equivalence. #570 is a deliberately introduced (commit eae79426, branch clearn-hero-model) flow-decomposition divergence (mdl/convert/stocks.rs) for a rank-changing subscripted flow, whose only mdl_equivalence.rs surface is the #[ignore]d test_clearn_equivalence -- a binding follow-up for the B2 PR (#559). Whatever fix-or-policy resolves the 'xmutil-gated equivalence assertions are outside the canonical gate' root class for #512 should account for #570 too.

  2. added
    engineIssues with the rust-based simulation engine
    compatCompatibility (XMILE, Vensim, etc) problem or enhancement
    bugSomething isn't working
    on Jun 8, 2026
  3. bpowers commented on Sep 4, 2026

    @bpowers
    OwnerAuthor

    Root cause identified (static read, 2026-09-03)

    Still reproduces on main (base of PR #1040, compiler-unification-v2) under cargo test -p simlin-engine --all-features (which enables xmutil), with the same numbers: xmutil 29 elements / link=13, native 32 / link=16. Re-observed independently in three of that branch's review reports.

    The 3 extra links

    They are sketch arrows 42, 43, 44 in src/libsimlin/testdata/SIR.mdl, all pointing INTO the stock Susceptible Population S (sketch id 1):

    1,42,2,1,0,0,0,0,0,64,1,-1--1--1,,1|(301,190)|   Infectious Population I  -> S
    1,43,15,1,0,0,0,0,0,64,1,-1--1--1,,1|(423,190)|  Recovered Population R   -> S
    1,44,24,1,0,0,0,0,0,64,1,-1--1--1,,1|(213,264)|  Total Population P       -> S
    

    These are exactly S's INTEG initial-value inputs (SIR.mdl:90-92):

    Susceptible Population S= INTEG (
    	-Infection Rate,
    		Total Population P - Infectious Population I -  Recovered Population R)
    

    They are not flow pipes (shape field is 0; pipe arrows in this file are shape 4/100 and originate at valves). They are the only arrows in the file with sketch field 10 = 1. The second SIR fixture in EQUIVALENT_MODELS, test/test-models/samples/SIR/SIR.mdl, has the identical pattern (arrow 21: Total Population -> stock Susceptible, shape 0, field10 = 1), so it will fail by 1 link as soon as the first fixture passes -- the test aborts at the first fixture, so every later fixture is currently unverified. What Vensim means by field 10 = 1 is unverified (plausibly its initial-value-arrow marker, since it co-occurs with to=stock in both fixtures); the diagnosis below does not depend on it.

    Why the two importers disagree

    • xmutil drops every connector whose to variable is a stock, unconditionally: src/xmutil/third_party/xmutil/Xmile/XMILEGenerator.cpp:1087-1090 (to->GetVariable()->VariableType() != XMILE_Type_STOCK gates "valid xmile connector"). That check exists to suppress flow-pipe arrows (valve -> stock, where xmutil has already redirected from to the flow variable), but it is broader than that and also eats initial-value arrows.
    • native drops connectors into stocks only when they are flow pipes: src/simlin-engine/src/mdl/view/convert.rs:827-836 (field4 == 4 || field4 == 100 || from_attached_valve || to_attached_valve), so ordinary causal arrows into a stock are kept as ViewElement::Links.

    13 shared links + 3 initial-value links = 16.

    Which side is right

    The native parser. Checked against the sources rather than assumed:

    • The XMILE spec's <connector> definition (docs/reference/xmile-v1.0.html, display section) says only "to REQUIRED -- The name of the model entity to which this connector ends"; it places no restriction on the target type. Connectors into stocks are legal XMILE.
    • The arrows are genuinely declared in the Vensim sketch and correspond one-for-one to real initial-value dependencies of the stock. Dropping them is lossy: a model roundtripped through the xmutil path loses arrows the author drew.

    So this is an xmutil (reference-side) limitation, not a native-parser bug, and the native parser should NOT be changed to match.

    Fix options

    1. Fix the reference: narrow xmutil's stock filter to to is stock AND from was an attached valve (mirroring the native rule), so only pipe arrows are suppressed. xmutil is test-only third-party code, so the blast radius is the xmutil-path fixtures; test/sdeverywhere xmutil-converted expectations would need re-checking.
    2. Normalize in the test: in tests/integration/mdl_equivalence.rs, drop native links whose to is a stock before comparing, with a comment naming this xmutil limitation and pointing here. Cheapest; keeps the assertion honest about what it does and does not check.

    Either way the comparison should then be run through the remaining 12 EQUIVALENT_MODELS fixtures, which have never been reached.

  4. changed the title [-]engine: test_mdl_equivalence fails on main -- native MDL parser emits 3 extra link elements for SIR.mdl[/-] [+]mdl: reader keeps 3 more SIR.mdl connectors than xmutil[/+] on Oct 12, 2026
  5. bpowers commented on Oct 12, 2026

    @bpowers
    OwnerAuthor

    Closing: already fixed on main.

    Obsolete: xmutil, the xmutil feature and tests/mdl_equivalence.rs were deleted in ea8367a (#1080); no src/xmutil directory, Cargo feature or equivalence test remains on main. The divergence was xmutil dropping every connector into a stock, not a reader bug, so there is nothing left to compare against.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcompatCompatibility (XMILE, Vensim, etc) problem or enhancementengineIssues with the rust-based simulation engine

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions