jssm 5.153.0 → 5.155.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/custom-elements.json +290 -4
- package/dist/cdn/instance.js +148 -1
- package/dist/cdn/viz.js +146 -1
- package/dist/cli/fsl-export-system-prompt.cjs +1 -1
- package/dist/cli/fsl-render.cjs +1 -1
- package/dist/cli/fsl.cjs +1 -1
- package/dist/cli/lib.cjs +1 -1
- package/dist/cli/lib.mjs +1 -1
- package/dist/deno/README.md +7 -7
- package/dist/deno/jssm.d.ts +64 -1
- package/dist/deno/jssm.js +1 -1
- package/dist/deno/jssm_types.d.ts +29 -1
- package/dist/jssm.es5.cjs +1 -1
- package/dist/jssm.es5.iife.js +1 -1
- package/dist/jssm.es6.mjs +1 -1
- package/dist/jssm_viz.cjs +1 -1
- package/dist/jssm_viz.iife.cjs +1 -1
- package/dist/jssm_viz.mjs +1 -1
- package/dist/wc/docs.js +3 -3
- package/dist/wc/instance.js +2 -0
- package/dist/wc/widgets.define.js +3 -2
- package/dist/wc/widgets.js +338 -41
- package/jssm.es5.d.cts +92 -1
- package/jssm.es6.d.ts +92 -1
- package/jssm_viz.es5.d.cts +87 -0
- package/jssm_viz.es6.d.ts +87 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,10 +18,10 @@ Please edit the file it's derived from, instead: `./src/md/readme_base.md`
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
* Generated for version 5.
|
|
21
|
+
* Generated for version 5.155.0 at 6/28/2026, 7:41:44 PM
|
|
22
22
|
|
|
23
23
|
-->
|
|
24
|
-
# jssm 5.
|
|
24
|
+
# jssm 5.155.0
|
|
25
25
|
|
|
26
26
|
[**Try the live editor**](https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html) ·
|
|
27
27
|
[Documentation](https://stonecypher.github.io/jssm/docs/) ·
|
|
@@ -312,7 +312,7 @@ That decision shows up everywhere downstream:
|
|
|
312
312
|
or run `npm run benny` against your own machine.
|
|
313
313
|
|
|
314
314
|
- **More thoroughly tested than any other JavaScript state-machine
|
|
315
|
-
library.** 7,
|
|
315
|
+
library.** 7,811 tests at 100.0% line coverage
|
|
316
316
|
([report](https://coveralls.io/github/StoneCypher/jssm)), plus
|
|
317
317
|
fuzz testing via `fast-check`, with parser test data across ten natural
|
|
318
318
|
languages and Emoji.
|
|
@@ -445,11 +445,11 @@ If your contribution is missing here, please open an issue.
|
|
|
445
445
|
|
|
446
446
|
<br/>
|
|
447
447
|
|
|
448
|
-
***7,
|
|
448
|
+
***7,811 tests***, run 82,853 times.
|
|
449
449
|
|
|
450
|
-
- 7,
|
|
451
|
-
-
|
|
452
|
-
- 9,
|
|
450
|
+
- 7,053 specs with 100.0% coverage
|
|
451
|
+
- 758 fuzz tests with 54.8% coverage
|
|
452
|
+
- 9,666 TypeScript lines - 0.8 tests per line, 8.6 generated tests per line
|
|
453
453
|
|
|
454
454
|
[](https://github.com/StoneCypher/jssm/actions)
|
|
455
455
|
[](https://www.npmjs.com/package/jssm)
|
package/custom-elements.json
CHANGED
|
@@ -444,7 +444,7 @@
|
|
|
444
444
|
"kind": "variable",
|
|
445
445
|
"name": "FSL_COLOR_KEYS",
|
|
446
446
|
"default": "new Set([ 'color', 'text-color', 'background-color', 'border-color', 'edge-color', ])",
|
|
447
|
-
"description": "Attribute keys whose value is a color, mirroring the editor's `COLOR_KEYS`\n(language_service). The value token following one of these (plus its `:`) is\ntagged `color` and rendered with a swatch, matching the editor overlay."
|
|
447
|
+
"description": "Attribute keys whose value is a color, mirroring the editor's `COLOR_KEYS`\r\n(language_service). The value token following one of these (plus its `:`) is\r\ntagged `color` and rendered with a swatch, matching the editor overlay."
|
|
448
448
|
},
|
|
449
449
|
{
|
|
450
450
|
"kind": "function",
|
|
@@ -462,7 +462,7 @@
|
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
464
|
],
|
|
465
|
-
"description": "Tokenize FSL source into `{cls, text}` runs for syntax highlighting. A pure,\nregex-driven scanner — never parses, so it cannot throw on malformed input.\n`cls` is null for uncategorized text (punctuation, identifiers, whitespace).\n\nBeyond the lexical classes it tracks one bit of structural context: an\nidentifier immediately before a `:` is retro-tagged `key` (an attribute key,\nunless it is already a `keyword`), and the value token after a color key's\ncolon — or any hex literal — is tagged `color`. The context never spans a\n`;`, so a value can't leak past its statement."
|
|
465
|
+
"description": "Tokenize FSL source into `{cls, text}` runs for syntax highlighting. A pure,\r\nregex-driven scanner — never parses, so it cannot throw on malformed input.\r\n`cls` is null for uncategorized text (punctuation, identifiers, whitespace).\r\n\r\nBeyond the lexical classes it tracks one bit of structural context: an\r\nidentifier immediately before a `:` is retro-tagged `key` (an attribute key,\r\nunless it is already a `keyword`), and the value token after a color key's\r\ncolon — or any hex literal — is tagged `color`. The context never spans a\r\n`;`, so a value can't leak past its statement."
|
|
466
466
|
},
|
|
467
467
|
{
|
|
468
468
|
"kind": "function",
|
|
@@ -480,7 +480,7 @@
|
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
482
|
],
|
|
483
|
-
"description": "Highlight FSL source to an HTML string of `<span class=\"fsl-tok-…\">` runs.\nA `color` token is preceded by an inline `<span class=\"fsl-swatch\">` whose\nbackground is the literal color text (a CSS-valid named color or hex), giving\nthe docs the same swatch the editor overlay shows. Color text is a hex or\nidentifier run, so it is a safe `background:` value."
|
|
483
|
+
"description": "Highlight FSL source to an HTML string of `<span class=\"fsl-tok-…\">` runs.\r\nA `color` token is preceded by an inline `<span class=\"fsl-swatch\">` whose\r\nbackground is the literal color text (a CSS-valid named color or hex), giving\r\nthe docs the same swatch the editor overlay shows. Color text is a hex or\r\nidentifier run, so it is a safe `background:` value."
|
|
484
484
|
},
|
|
485
485
|
{
|
|
486
486
|
"kind": "function",
|
|
@@ -558,7 +558,7 @@
|
|
|
558
558
|
"declarations": [
|
|
559
559
|
{
|
|
560
560
|
"kind": "class",
|
|
561
|
-
"description": "`<fsl-docs>` — the language-docs content engine: drill-in nav over the bundled\ncurriculum (Getting Started / About State Machines / Tutorials / Example\nMachines / Index / Search), a markdown page renderer, and \"load into editor\"\nfor tagged FSL examples. Content-only; slot it into `<fsl-help>`.",
|
|
561
|
+
"description": "`<fsl-docs>` — the language-docs content engine: drill-in nav over the bundled\r\ncurriculum (Getting Started / About State Machines / Tutorials / Example\r\nMachines / Index / Search), a markdown page renderer, and \"load into editor\"\r\nfor tagged FSL examples. Content-only; slot it into `<fsl-help>`.",
|
|
562
562
|
"name": "FslDocs",
|
|
563
563
|
"members": [
|
|
564
564
|
{
|
|
@@ -2138,6 +2138,10 @@
|
|
|
2138
2138
|
"description": "Slot for the random-walk simulation (`<fsl-simulation>`, #668).",
|
|
2139
2139
|
"name": "simulation"
|
|
2140
2140
|
},
|
|
2141
|
+
{
|
|
2142
|
+
"description": "Slot for the stochastic analysis panel (`<fsl-stochastic>`, fsl#1384).",
|
|
2143
|
+
"name": "stochastic"
|
|
2144
|
+
},
|
|
2141
2145
|
{
|
|
2142
2146
|
"description": "Slot for the export menu (`<fsl-export>`, #667).",
|
|
2143
2147
|
"name": "export"
|
|
@@ -3653,6 +3657,280 @@
|
|
|
3653
3657
|
}
|
|
3654
3658
|
]
|
|
3655
3659
|
},
|
|
3660
|
+
{
|
|
3661
|
+
"kind": "javascript-module",
|
|
3662
|
+
"path": "src/ts/wc/fsl_stochastic_wc.ts",
|
|
3663
|
+
"declarations": [
|
|
3664
|
+
{
|
|
3665
|
+
"kind": "class",
|
|
3666
|
+
"description": "`<fsl-stochastic>` — a statistical/Monte-Carlo explorer for a parent\r\n`<fsl-instance>` (fsl#1384). Builds its own throwaway machine from the\r\nhost's `.fsl` source (never touching the live machine) and renders\r\naggregate run statistics in-panel. Standalone (no host) the controls are\r\ndisabled.",
|
|
3667
|
+
"name": "FslStochastic",
|
|
3668
|
+
"cssParts": [
|
|
3669
|
+
{
|
|
3670
|
+
"description": "The control row.",
|
|
3671
|
+
"name": "controls"
|
|
3672
|
+
}
|
|
3673
|
+
],
|
|
3674
|
+
"members": [
|
|
3675
|
+
{
|
|
3676
|
+
"kind": "field",
|
|
3677
|
+
"name": "runs",
|
|
3678
|
+
"default": "STOCHASTIC_DEFAULT_RUNS",
|
|
3679
|
+
"description": "Run-count (montecarlo). Defaults from editor_config().stochastic_run_count.",
|
|
3680
|
+
"attribute": "runs"
|
|
3681
|
+
},
|
|
3682
|
+
{
|
|
3683
|
+
"kind": "field",
|
|
3684
|
+
"name": "maxSteps",
|
|
3685
|
+
"default": "STOCHASTIC_DEFAULT_MAX_STEPS",
|
|
3686
|
+
"description": "Per-run step cap (montecarlo) / walk length (steady_state).",
|
|
3687
|
+
"attribute": "maxSteps"
|
|
3688
|
+
},
|
|
3689
|
+
{
|
|
3690
|
+
"kind": "field",
|
|
3691
|
+
"name": "seed",
|
|
3692
|
+
"type": {
|
|
3693
|
+
"text": "string"
|
|
3694
|
+
},
|
|
3695
|
+
"default": "''",
|
|
3696
|
+
"description": "Seed string ('' = time-based). Kept as string so the field can be blank.",
|
|
3697
|
+
"attribute": "seed"
|
|
3698
|
+
},
|
|
3699
|
+
{
|
|
3700
|
+
"kind": "field",
|
|
3701
|
+
"name": "mode",
|
|
3702
|
+
"type": {
|
|
3703
|
+
"text": "JssmStochasticMode"
|
|
3704
|
+
},
|
|
3705
|
+
"default": "'montecarlo'",
|
|
3706
|
+
"description": "Run mode.",
|
|
3707
|
+
"attribute": "mode"
|
|
3708
|
+
},
|
|
3709
|
+
{
|
|
3710
|
+
"kind": "field",
|
|
3711
|
+
"name": "_summary",
|
|
3712
|
+
"type": {
|
|
3713
|
+
"text": "JssmStochasticSummary | null"
|
|
3714
|
+
},
|
|
3715
|
+
"privacy": "private",
|
|
3716
|
+
"default": "null"
|
|
3717
|
+
},
|
|
3718
|
+
{
|
|
3719
|
+
"kind": "field",
|
|
3720
|
+
"name": "_error",
|
|
3721
|
+
"type": {
|
|
3722
|
+
"text": "string | null"
|
|
3723
|
+
},
|
|
3724
|
+
"privacy": "private",
|
|
3725
|
+
"default": "null"
|
|
3726
|
+
},
|
|
3727
|
+
{
|
|
3728
|
+
"kind": "field",
|
|
3729
|
+
"name": "_host",
|
|
3730
|
+
"type": {
|
|
3731
|
+
"text": "StochHost | null"
|
|
3732
|
+
},
|
|
3733
|
+
"privacy": "private",
|
|
3734
|
+
"default": "null"
|
|
3735
|
+
},
|
|
3736
|
+
{
|
|
3737
|
+
"kind": "field",
|
|
3738
|
+
"name": "_playing",
|
|
3739
|
+
"type": {
|
|
3740
|
+
"text": "boolean"
|
|
3741
|
+
},
|
|
3742
|
+
"privacy": "private",
|
|
3743
|
+
"default": "false"
|
|
3744
|
+
},
|
|
3745
|
+
{
|
|
3746
|
+
"kind": "field",
|
|
3747
|
+
"name": "run",
|
|
3748
|
+
"description": "Execute a batch synchronously and render the aggregates."
|
|
3749
|
+
},
|
|
3750
|
+
{
|
|
3751
|
+
"kind": "field",
|
|
3752
|
+
"name": "play",
|
|
3753
|
+
"description": "Animate the batch: accumulate runs incrementally via `requestAnimationFrame`,\r\nredrawing as they land. Resolves when the batch completes or is paused-to-stop.\r\n\r\nFalls back to immediate (synchronous chunk) scheduling under jsdom where\r\n`requestAnimationFrame` is undefined."
|
|
3754
|
+
},
|
|
3755
|
+
{
|
|
3756
|
+
"kind": "method",
|
|
3757
|
+
"name": "_commit",
|
|
3758
|
+
"privacy": "private",
|
|
3759
|
+
"return": {
|
|
3760
|
+
"type": {
|
|
3761
|
+
"text": "void"
|
|
3762
|
+
}
|
|
3763
|
+
},
|
|
3764
|
+
"parameters": [
|
|
3765
|
+
{
|
|
3766
|
+
"name": "state_visits",
|
|
3767
|
+
"type": {
|
|
3768
|
+
"text": "Map<string, number>"
|
|
3769
|
+
},
|
|
3770
|
+
"description": "Accumulated visit counts per state name."
|
|
3771
|
+
},
|
|
3772
|
+
{
|
|
3773
|
+
"name": "edge_traversals",
|
|
3774
|
+
"type": {
|
|
3775
|
+
"text": "Map<string, number>"
|
|
3776
|
+
},
|
|
3777
|
+
"description": "Accumulated traversal counts per edge key."
|
|
3778
|
+
},
|
|
3779
|
+
{
|
|
3780
|
+
"name": "path_lengths",
|
|
3781
|
+
"type": {
|
|
3782
|
+
"text": "number[]"
|
|
3783
|
+
},
|
|
3784
|
+
"description": "Lengths of completed (terminated) paths."
|
|
3785
|
+
},
|
|
3786
|
+
{
|
|
3787
|
+
"name": "terminal_reached",
|
|
3788
|
+
"type": {
|
|
3789
|
+
"text": "number"
|
|
3790
|
+
},
|
|
3791
|
+
"description": "Count of runs that reached a terminal state."
|
|
3792
|
+
},
|
|
3793
|
+
{
|
|
3794
|
+
"name": "capped",
|
|
3795
|
+
"type": {
|
|
3796
|
+
"text": "number"
|
|
3797
|
+
},
|
|
3798
|
+
"description": "Count of runs that hit the step cap."
|
|
3799
|
+
},
|
|
3800
|
+
{
|
|
3801
|
+
"name": "runs",
|
|
3802
|
+
"type": {
|
|
3803
|
+
"text": "number"
|
|
3804
|
+
},
|
|
3805
|
+
"description": "Total runs processed so far."
|
|
3806
|
+
},
|
|
3807
|
+
{
|
|
3808
|
+
"name": "seed",
|
|
3809
|
+
"type": {
|
|
3810
|
+
"text": "number"
|
|
3811
|
+
},
|
|
3812
|
+
"description": "The effective RNG seed used for this batch."
|
|
3813
|
+
}
|
|
3814
|
+
],
|
|
3815
|
+
"description": "Fold accumulated counters into a rendered summary. Shared by play\r\nfor incremental rendering during animation."
|
|
3816
|
+
},
|
|
3817
|
+
{
|
|
3818
|
+
"kind": "field",
|
|
3819
|
+
"name": "_togglePlay",
|
|
3820
|
+
"privacy": "private",
|
|
3821
|
+
"description": "Toggle between playing and paused. Starts a new play batch when idle."
|
|
3822
|
+
},
|
|
3823
|
+
{
|
|
3824
|
+
"kind": "field",
|
|
3825
|
+
"name": "_onMode",
|
|
3826
|
+
"privacy": "private"
|
|
3827
|
+
},
|
|
3828
|
+
{
|
|
3829
|
+
"kind": "field",
|
|
3830
|
+
"name": "_onRuns",
|
|
3831
|
+
"privacy": "private"
|
|
3832
|
+
},
|
|
3833
|
+
{
|
|
3834
|
+
"kind": "field",
|
|
3835
|
+
"name": "_onMax",
|
|
3836
|
+
"privacy": "private"
|
|
3837
|
+
},
|
|
3838
|
+
{
|
|
3839
|
+
"kind": "field",
|
|
3840
|
+
"name": "_onSeed",
|
|
3841
|
+
"privacy": "private"
|
|
3842
|
+
},
|
|
3843
|
+
{
|
|
3844
|
+
"kind": "method",
|
|
3845
|
+
"name": "_bars",
|
|
3846
|
+
"privacy": "private",
|
|
3847
|
+
"return": {
|
|
3848
|
+
"type": {
|
|
3849
|
+
"text": "TemplateResult"
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
3852
|
+
},
|
|
3853
|
+
{
|
|
3854
|
+
"kind": "method",
|
|
3855
|
+
"name": "_panes",
|
|
3856
|
+
"privacy": "private",
|
|
3857
|
+
"return": {
|
|
3858
|
+
"type": {
|
|
3859
|
+
"text": "TemplateResult"
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3863
|
+
],
|
|
3864
|
+
"events": [
|
|
3865
|
+
{
|
|
3866
|
+
"description": "CustomEvent<JssmStochasticSummary> after a run.",
|
|
3867
|
+
"name": "fsl-stochastic-complete"
|
|
3868
|
+
}
|
|
3869
|
+
],
|
|
3870
|
+
"attributes": [
|
|
3871
|
+
{
|
|
3872
|
+
"name": "runs",
|
|
3873
|
+
"default": "STOCHASTIC_DEFAULT_RUNS",
|
|
3874
|
+
"description": "Run-count (montecarlo). Defaults from editor_config().stochastic_run_count.",
|
|
3875
|
+
"fieldName": "runs"
|
|
3876
|
+
},
|
|
3877
|
+
{
|
|
3878
|
+
"name": "maxSteps",
|
|
3879
|
+
"default": "STOCHASTIC_DEFAULT_MAX_STEPS",
|
|
3880
|
+
"description": "Per-run step cap (montecarlo) / walk length (steady_state).",
|
|
3881
|
+
"fieldName": "maxSteps"
|
|
3882
|
+
},
|
|
3883
|
+
{
|
|
3884
|
+
"name": "seed",
|
|
3885
|
+
"type": {
|
|
3886
|
+
"text": "string"
|
|
3887
|
+
},
|
|
3888
|
+
"default": "''",
|
|
3889
|
+
"description": "Seed string ('' = time-based). Kept as string so the field can be blank.",
|
|
3890
|
+
"fieldName": "seed"
|
|
3891
|
+
},
|
|
3892
|
+
{
|
|
3893
|
+
"name": "mode",
|
|
3894
|
+
"type": {
|
|
3895
|
+
"text": "JssmStochasticMode"
|
|
3896
|
+
},
|
|
3897
|
+
"default": "'montecarlo'",
|
|
3898
|
+
"description": "Run mode.",
|
|
3899
|
+
"fieldName": "mode"
|
|
3900
|
+
}
|
|
3901
|
+
],
|
|
3902
|
+
"superclass": {
|
|
3903
|
+
"name": "LitElement",
|
|
3904
|
+
"package": "lit"
|
|
3905
|
+
},
|
|
3906
|
+
"tagName": "fsl-stochastic",
|
|
3907
|
+
"customElement": true
|
|
3908
|
+
},
|
|
3909
|
+
{
|
|
3910
|
+
"kind": "variable",
|
|
3911
|
+
"name": "state_visits",
|
|
3912
|
+
"default": "new Map<string, number>()"
|
|
3913
|
+
},
|
|
3914
|
+
{
|
|
3915
|
+
"kind": "variable",
|
|
3916
|
+
"name": "runs",
|
|
3917
|
+
"type": {
|
|
3918
|
+
"text": "number"
|
|
3919
|
+
},
|
|
3920
|
+
"default": "0"
|
|
3921
|
+
}
|
|
3922
|
+
],
|
|
3923
|
+
"exports": [
|
|
3924
|
+
{
|
|
3925
|
+
"kind": "js",
|
|
3926
|
+
"name": "FslStochastic",
|
|
3927
|
+
"declaration": {
|
|
3928
|
+
"name": "FslStochastic",
|
|
3929
|
+
"module": "src/ts/wc/fsl_stochastic_wc.ts"
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3932
|
+
]
|
|
3933
|
+
},
|
|
3656
3934
|
{
|
|
3657
3935
|
"kind": "javascript-module",
|
|
3658
3936
|
"path": "src/ts/wc/fsl_themes.ts",
|
|
@@ -4603,6 +4881,14 @@
|
|
|
4603
4881
|
"name": "FslExport",
|
|
4604
4882
|
"module": "./fsl_export_wc.js"
|
|
4605
4883
|
}
|
|
4884
|
+
},
|
|
4885
|
+
{
|
|
4886
|
+
"kind": "js",
|
|
4887
|
+
"name": "FslStochastic",
|
|
4888
|
+
"declaration": {
|
|
4889
|
+
"name": "FslStochastic",
|
|
4890
|
+
"module": "./fsl_stochastic_wc.js"
|
|
4891
|
+
}
|
|
4606
4892
|
}
|
|
4607
4893
|
]
|
|
4608
4894
|
}
|
package/dist/cdn/instance.js
CHANGED
|
@@ -23563,7 +23563,7 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
23563
23563
|
* Useful for runtime diagnostics and for embedding in serialized machine
|
|
23564
23564
|
* snapshots so that deserializers can detect version-skew.
|
|
23565
23565
|
*/
|
|
23566
|
-
const version = "5.
|
|
23566
|
+
const version = "5.155.0";
|
|
23567
23567
|
|
|
23568
23568
|
// whargarbl lots of these return arrays could/should be sets
|
|
23569
23569
|
const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
|
|
@@ -23878,6 +23878,10 @@ function find_connected_components(states, edges) {
|
|
|
23878
23878
|
}
|
|
23879
23879
|
return result;
|
|
23880
23880
|
}
|
|
23881
|
+
/** Default number of independent Monte-Carlo runs when none is declared. */
|
|
23882
|
+
const STOCHASTIC_DEFAULT_RUNS = 1000;
|
|
23883
|
+
/** Default per-run step cap (montecarlo) / walk length (steady_state). */
|
|
23884
|
+
const STOCHASTIC_DEFAULT_MAX_STEPS = 1000;
|
|
23881
23885
|
class Machine {
|
|
23882
23886
|
// whargarbl this badly needs to be broken up, monolith master
|
|
23883
23887
|
constructor({ start_states, end_states = [], failed_outputs = [], initial_state, start_states_no_enforce, complete = [], transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, npm_name, default_size, state_declaration, property_definition, state_property, fsl_version, dot_preamble = undefined, arrange_declaration = [], arrange_start_declaration = [], arrange_end_declaration = [], oarrange_declaration = [], farrange_declaration = [], theme = ['default'], flow = 'down', graph_layout = 'dot', instance_name, history, boundary_depth_limit, data, default_state_config, default_active_state_config, default_hooked_state_config, default_terminal_state_config, default_start_state_config, default_end_state_config, default_transition_config, default_graph_config, group_registry, group_metadata, group_hooks, state_hooks, allows_override, config_allows_override, allow_islands, editor_config, rng_seed, time_source, timeout_source, clear_timeout_source }) {
|
|
@@ -25394,6 +25398,147 @@ class Machine {
|
|
|
25394
25398
|
probabilistic_histo_walk(n) {
|
|
25395
25399
|
return histograph(this.probabilistic_walk(n));
|
|
25396
25400
|
}
|
|
25401
|
+
/** One non-destructive weighted-random walk over the graph from `start`.
|
|
25402
|
+
*
|
|
25403
|
+
* Reads the graph and advances the PRNG only — it never calls
|
|
25404
|
+
* {@link Machine.transition}, so it fires no hooks, mutates no machine
|
|
25405
|
+
* state, and touches no `data`. A state with no probabilistic exits
|
|
25406
|
+
* (a terminal, or a forced-only `~>` state) ends the walk.
|
|
25407
|
+
*
|
|
25408
|
+
* @param start - State to begin the walk from.
|
|
25409
|
+
* @param max_steps - Maximum transitions before the walk is step-capped.
|
|
25410
|
+
* @returns The {@link JssmStochasticRun} for this walk.
|
|
25411
|
+
*/
|
|
25412
|
+
_stochastic_one_walk(start, max_steps) {
|
|
25413
|
+
const states = [start];
|
|
25414
|
+
const edges = [];
|
|
25415
|
+
let cur = start;
|
|
25416
|
+
let terminated = false;
|
|
25417
|
+
for (let step = 0; step < max_steps; step++) {
|
|
25418
|
+
const exits = this.probable_exits_for(cur);
|
|
25419
|
+
if (exits.length === 0) {
|
|
25420
|
+
terminated = true;
|
|
25421
|
+
break;
|
|
25422
|
+
}
|
|
25423
|
+
const selected = weighted_rand_select(exits, undefined, this._rng);
|
|
25424
|
+
edges.push(`${cur}→${selected.to}`);
|
|
25425
|
+
cur = selected.to;
|
|
25426
|
+
states.push(cur);
|
|
25427
|
+
}
|
|
25428
|
+
return { states, edges, length: states.length - 1, terminated };
|
|
25429
|
+
}
|
|
25430
|
+
/** Lazily yield one {@link JssmStochasticRun} at a time.
|
|
25431
|
+
*
|
|
25432
|
+
* In `montecarlo` mode (default) yields `runs` independent walks from the
|
|
25433
|
+
* current state, each ending at a terminal or after `max_steps`. In
|
|
25434
|
+
* `steady_state` mode yields exactly one walk of `max_steps` steps. This
|
|
25435
|
+
* is the lazy engine behind {@link Machine.stochastic_summary}; the
|
|
25436
|
+
* fsl-stochastic panel drives it across animation frames.
|
|
25437
|
+
*
|
|
25438
|
+
* Passing `seed` reseeds the machine for reproducible runs. Unlike
|
|
25439
|
+
* {@link Machine.stochastic_summary}, the generator does NOT restore the
|
|
25440
|
+
* prior seed afterward — a direct caller's machine is left reseeded.
|
|
25441
|
+
*
|
|
25442
|
+
* @param opts - {@link JssmStochasticOptions}.
|
|
25443
|
+
* @returns A generator of per-run results.
|
|
25444
|
+
*
|
|
25445
|
+
* @example
|
|
25446
|
+
* const m = sm`a 'go' -> b 'go' -> c;`;
|
|
25447
|
+
* [...m.stochastic_runs({ runs: 2, seed: 1 })].length; // => 2
|
|
25448
|
+
*/
|
|
25449
|
+
*stochastic_runs(opts = {}) {
|
|
25450
|
+
var _a, _b, _c, _d, _e;
|
|
25451
|
+
if (opts.seed !== undefined) {
|
|
25452
|
+
this.rng_seed = opts.seed;
|
|
25453
|
+
}
|
|
25454
|
+
const mode = (_a = opts.mode) !== null && _a !== void 0 ? _a : 'montecarlo';
|
|
25455
|
+
const max_steps = (_b = opts.max_steps) !== null && _b !== void 0 ? _b : STOCHASTIC_DEFAULT_MAX_STEPS;
|
|
25456
|
+
const runs = (mode === 'steady_state')
|
|
25457
|
+
? 1
|
|
25458
|
+
: ((_e = (_c = opts.runs) !== null && _c !== void 0 ? _c : (_d = this.editor_config()) === null || _d === void 0 ? void 0 : _d.stochastic_run_count) !== null && _e !== void 0 ? _e : STOCHASTIC_DEFAULT_RUNS);
|
|
25459
|
+
const start = this.state();
|
|
25460
|
+
for (let i = 0; i < runs; i++) {
|
|
25461
|
+
yield this._stochastic_one_walk(start, max_steps);
|
|
25462
|
+
}
|
|
25463
|
+
}
|
|
25464
|
+
/** Run many weighted-random walks and return aggregate statistics.
|
|
25465
|
+
*
|
|
25466
|
+
* Honors `%` transition probabilities (via the existing probabilistic
|
|
25467
|
+
* machinery). Non-destructive: the machine's current state and
|
|
25468
|
+
* {@link Machine.rng_seed} are restored before returning, so calling this
|
|
25469
|
+
* never perturbs the live machine. `montecarlo` mode (default) reports
|
|
25470
|
+
* per-run `path_lengths`, `terminal_reached`, and `capped`; `steady_state`
|
|
25471
|
+
* mode runs one long walk and omits those fields.
|
|
25472
|
+
*
|
|
25473
|
+
* Timing (`after`) decorations and data-guard conditions are not modeled
|
|
25474
|
+
* by this sampler; it walks the probabilistic graph topology.
|
|
25475
|
+
*
|
|
25476
|
+
* @param opts - {@link JssmStochasticOptions}. `runs` defaults to the
|
|
25477
|
+
* machine's declared `editor: { stochastic_run_count }` (fsl#1334) when
|
|
25478
|
+
* present, otherwise {@link STOCHASTIC_DEFAULT_RUNS}.
|
|
25479
|
+
* @returns A {@link JssmStochasticSummary}.
|
|
25480
|
+
*
|
|
25481
|
+
* @see Machine.stochastic_runs
|
|
25482
|
+
* @see Machine.probabilistic_walk
|
|
25483
|
+
* @see Machine.editor_config
|
|
25484
|
+
*
|
|
25485
|
+
* @example
|
|
25486
|
+
* const m = sm`a 'go' -> b 'go' -> c;`;
|
|
25487
|
+
* const s = m.stochastic_summary({ runs: 100, seed: 1 });
|
|
25488
|
+
* s.terminal_reached; // => 100
|
|
25489
|
+
*/
|
|
25490
|
+
stochastic_summary(opts = {}) {
|
|
25491
|
+
var _a, _b, _c;
|
|
25492
|
+
const mode = (_a = opts.mode) !== null && _a !== void 0 ? _a : 'montecarlo';
|
|
25493
|
+
const saved_seed = this._rng_seed;
|
|
25494
|
+
if (opts.seed !== undefined) {
|
|
25495
|
+
this.rng_seed = opts.seed;
|
|
25496
|
+
}
|
|
25497
|
+
const effective_seed = this._rng_seed;
|
|
25498
|
+
const state_visits = new Map();
|
|
25499
|
+
const edge_traversals = new Map();
|
|
25500
|
+
const path_lengths = [];
|
|
25501
|
+
let terminal_reached = 0, capped = 0, runs = 0;
|
|
25502
|
+
try {
|
|
25503
|
+
for (const run of this.stochastic_runs(Object.assign(Object.assign({}, opts), { mode }))) {
|
|
25504
|
+
runs += 1;
|
|
25505
|
+
for (const s of run.states) {
|
|
25506
|
+
state_visits.set(s, ((_b = state_visits.get(s)) !== null && _b !== void 0 ? _b : 0) + 1);
|
|
25507
|
+
}
|
|
25508
|
+
for (const e of run.edges) {
|
|
25509
|
+
edge_traversals.set(e, ((_c = edge_traversals.get(e)) !== null && _c !== void 0 ? _c : 0) + 1);
|
|
25510
|
+
}
|
|
25511
|
+
if (mode === 'montecarlo') {
|
|
25512
|
+
if (run.terminated) {
|
|
25513
|
+
terminal_reached += 1;
|
|
25514
|
+
path_lengths.push(run.length);
|
|
25515
|
+
}
|
|
25516
|
+
else {
|
|
25517
|
+
capped += 1;
|
|
25518
|
+
}
|
|
25519
|
+
}
|
|
25520
|
+
}
|
|
25521
|
+
}
|
|
25522
|
+
finally {
|
|
25523
|
+
// restore the PRNG so the call is non-destructive even when the loop throws
|
|
25524
|
+
this.rng_seed = saved_seed;
|
|
25525
|
+
}
|
|
25526
|
+
const total_visits = [...state_visits.values()].reduce((a, b) => a + b, 0);
|
|
25527
|
+
const state_visit_fraction = new Map();
|
|
25528
|
+
for (const [s, c] of state_visits) {
|
|
25529
|
+
state_visit_fraction.set(s, c / total_visits);
|
|
25530
|
+
}
|
|
25531
|
+
const summary = {
|
|
25532
|
+
mode, runs, seed: effective_seed,
|
|
25533
|
+
state_visits, state_visit_fraction, edge_traversals,
|
|
25534
|
+
};
|
|
25535
|
+
if (mode === 'montecarlo') {
|
|
25536
|
+
summary.path_lengths = path_lengths;
|
|
25537
|
+
summary.terminal_reached = terminal_reached;
|
|
25538
|
+
summary.capped = capped;
|
|
25539
|
+
}
|
|
25540
|
+
return summary;
|
|
25541
|
+
}
|
|
25397
25542
|
/********
|
|
25398
25543
|
*
|
|
25399
25544
|
* List all actions available from this state. Please note that the order of
|
|
@@ -29860,6 +30005,7 @@ function split_ratio(coord, start, size) {
|
|
|
29860
30005
|
* @slot hook-log - Slot for the hook-firing log (`<fsl-hook-log>`, #664).
|
|
29861
30006
|
* @slot effective-properties - Slot for the resolved-properties panel (`<fsl-effective-properties>`, #665).
|
|
29862
30007
|
* @slot simulation - Slot for the random-walk simulation (`<fsl-simulation>`, #668).
|
|
30008
|
+
* @slot stochastic - Slot for the stochastic analysis panel (`<fsl-stochastic>`, fsl#1384).
|
|
29863
30009
|
* @slot export - Slot for the export menu (`<fsl-export>`, #667).
|
|
29864
30010
|
* @slot footer - Footer slot.
|
|
29865
30011
|
*/
|
|
@@ -30737,6 +30883,7 @@ class FslInstance extends i {
|
|
|
30737
30883
|
${docked ? '' : b `<section class="hook-log" ?hidden=${h('hook-log')}><slot name="hook-log"></slot></section>`}
|
|
30738
30884
|
<section class="effective-properties" ?hidden=${h('effective-properties')}><slot name="effective-properties"></slot></section>
|
|
30739
30885
|
<section class="simulation" ?hidden=${h('simulation')}><slot name="simulation"></slot></section>
|
|
30886
|
+
<section class="stochastic" ?hidden=${h('stochastic')}><slot name="stochastic"></slot></section>
|
|
30740
30887
|
<section class="export" ?hidden=${h('export')}><slot name="export"></slot></section>
|
|
30741
30888
|
`;
|
|
30742
30889
|
}
|