You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ltm: decide whether to support Stella's LOOPSCORE and PATHSCORE #484
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)
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:
There is no language-level LOOPSCORE/PATHSCORE builtin a user can write in an equation.
Loops that the heuristic doesn't discover get no synthetic variable, so even introspecting the synthetic naming doesn't help.
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)
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.
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.
Both should validate that consecutive variables share a causal edge in the model and emit a clear error if not.
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
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
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
Activity
bpowers commentedon May 9, 2026
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.
LOOPSCOREguarantees 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): withoutLOOPSCORE, 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.PATHSCOREserves 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 bymodel_ltm_variablesfor every loop and pathway the engine discovers. But:LOOPSCORE/PATHSCOREbuiltin a user can write in an equation.Proposed scope (incremental)
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.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.loop_scoreID system (r1,b1,u1) could be extended to allowLOOPSCORE_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
src/simlin-engine/src/db_ltm.rs:2997-3058src/simlin-engine/src/ltm_augment.rs:486-538src/simlin-engine/src/builtins.rssrc/simlin-engine/src/compiler/Paper references
docs/reference/ltm--loops-that-matter.mdSection 10[-]ltm: implement LOOPSCORE and PATHSCORE builtins for user-pinned loops[/-][+]ltm: LOOPSCORE and PATHSCORE builtins are not supported[/+][-]ltm: LOOPSCORE and PATHSCORE builtins are not supported[/-][+]ltm: decide whether to support Stella's LOOPSCORE and PATHSCORE[/+]