Skip to content

ltm: decide whether to support Stella's LOOPSCORE and PATHSCORE #484

Open

Description

@bpowers

Owner decision: close this as "won't build", or implement PATHSCORE.

The LTM papers describe two Stella equation builtins, LOOPSCORE (always score a named loop) and PATHSCORE (the score of a named causal path, usable in model equations).
Simlin has neither.
Pinned loops cover the LOOPSCORE need: a modeler names a loop's variables and the engine always scores it, readable by id (pin1) from libsimlin and pysimlin.

What closing would leave unsupported:

  • A model that calls either name gets the generic "'pathscore' is not a known function" error.
  • A loop score cannot be read inside a model equation.
  • A pinned variable set that forms two different cycles (A->B->C->A and A->C->B->A) scores only the alphabetically first one.

No real model or user report uses either builtin.

Fix

Recommended: close.
The unknown-function error is clear enough, and feeding a path score back into equations would make the model depend on the LTM pass.
Alternative: build PATHSCORE as a product of existing link scores when a real model needs it (M).

Pointers

  • src/simlin-engine/src/db/ltm/pinned.rs
  • src/simlin-engine/src/ltm/graph.rs: order_variable_cycle (the alphabetical tie-break)
  • docs/reference/ltm--loops-that-matter.md, section 10

Activity

  1. added
    enhancementNew feature or request
    engineIssues with the rust-based simulation engine
    ltmLoops that Matter (LTM) analysis subsystem
    on May 1, 2026
  2. bpowers commented on May 9, 2026

    @bpowers
    OwnerAuthor

    Additional analysis (filed via track-issue)

    Confirming this issue covers the gap. Adding deeper technical context and a more concrete proposed scope.

    Why this matters (beyond capability gap framing)

    The strongest-path discovery algorithm is heuristic -- its results change with parameterization, so a loop that's important in scenario A may not be discovered in scenario B. LOOPSCORE guarantees that a user-specified loop is always reported regardless of whether the discovery algorithm surfaced it. This is the most material functional gap relative to the LTM literature (Schoenberg & Eberlein 2020, Section 4.3): without LOOPSCORE, Simlin LTM users have to take whatever the strongest-path algorithm gives them. That's fine for the dominant loops in any given run, but limits Monte Carlo / sensitivity workflows where the user has a hypothesis about a specific loop and wants to track it across many runs.

    PATHSCORE serves the dual purpose of letting users probe specific causal pathways through macros / modules.

    Current state -- what already exists

    The synthetic variables $⁚ltm⁚loop_score⁚{id} and $⁚ltm⁚path⁚{port}⁚{idx} already exist in the augmented model -- they are emitted by model_ltm_variables for every loop and pathway the engine discovers. But:

    1. There is no language-level LOOPSCORE/PATHSCORE builtin a user can write in an equation.
    2. Loops that the heuristic doesn't discover get no synthetic variable, so even introspecting the synthetic naming doesn't help.
    3. A user wanting "track loop X across all my parameter sweeps" has no way to do it without manually computing the link product themselves in the equation language.

    Proposed scope (incremental)

    1. LOOPSCORE(var1, var2, ..., varN) -- user specifies the loop by listing its variables in cycle order. Simlin verifies the cycle exists in the causal graph, allocates a synthetic $⁚ltm⁚user_loop_score⁚{hash} if not already present, and emits the loop score. Returns a relative loop score (normalized within the appropriate cycle partition) at end of simulation.
    2. PATHSCORE(var1, var2, ..., varN) -- analogous for a non-cycle path. Returns the raw path score (product of link scores) at the current timestep, available during simulation.
    3. Both should validate that consecutive variables share a causal edge in the model and emit a clear error if not.
    4. The existing user-facing loop_score ID system (r1, b1, u1) could be extended to allow LOOPSCORE_BY_ID("r3") for users who'd rather reference discovered loops by ID -- but this depends on stable IDs across runs, which isn't guaranteed for discovery-mode results.

    Concrete file references

    • Existing synthetic var emission: src/simlin-engine/src/db_ltm.rs:2997-3058
    • Loop score equation generator: src/simlin-engine/src/ltm_augment.rs:486-538
    • Builtin function registry: src/simlin-engine/src/builtins.rs
    • Builtin-to-bytecode lowering: src/simlin-engine/src/compiler/

    Paper references

    • Schoenberg & Eberlein 2020 "Seamlessly Integrating LTM into Model Development and Analysis," Section 4.3
    • docs/reference/ltm--loops-that-matter.md Section 10
  3. changed the title [-]ltm: implement LOOPSCORE and PATHSCORE builtins for user-pinned loops[/-] [+]ltm: LOOPSCORE and PATHSCORE builtins are not supported[/+] on Oct 12, 2026
  4. changed the title [-]ltm: LOOPSCORE and PATHSCORE builtins are not supported[/-] [+]ltm: decide whether to support Stella's LOOPSCORE and PATHSCORE[/+] on Oct 12, 2026
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

    engineIssues with the rust-based simulation engineenhancementNew feature or requestltmLoops that Matter (LTM) analysis subsystem

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions