jssm 5.152.0 → 5.154.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 +293 -7
- package/dist/cdn/instance.js +352 -11
- package/dist/cdn/viz.js +374 -16
- 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 +70 -5
- package/dist/deno/jssm.js +1 -1
- package/dist/deno/jssm_types.d.ts +31 -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/instance.js +2 -0
- package/dist/wc/widgets.define.js +3 -2
- package/dist/wc/widgets.js +331 -34
- package/jssm.es5.d.cts +100 -5
- package/jssm.es6.d.ts +100 -5
- package/jssm_viz.es5.d.cts +95 -4
- package/jssm_viz.es6.d.ts +95 -4
- package/package.json +1 -1
package/dist/cdn/viz.js
CHANGED
|
@@ -913,7 +913,19 @@ function peg$parse(input, options) {
|
|
|
913
913
|
node.loc = location();
|
|
914
914
|
}
|
|
915
915
|
return node;
|
|
916
|
-
}, peg$c1573 = peg$otherExpectation("
|
|
916
|
+
}, peg$c1573 = peg$otherExpectation("oarrange declaration"), peg$c1574 = "oarrange", peg$c1575 = peg$literalExpectation("oarrange", false), peg$c1576 = function (value) {
|
|
917
|
+
const node = { key: 'oarrange_declaration', value };
|
|
918
|
+
if (options.locations) {
|
|
919
|
+
node.loc = location();
|
|
920
|
+
}
|
|
921
|
+
return node;
|
|
922
|
+
}, peg$c1577 = peg$otherExpectation("farrange declaration"), peg$c1578 = "farrange", peg$c1579 = peg$literalExpectation("farrange", false), peg$c1580 = function (value) {
|
|
923
|
+
const node = { key: 'farrange_declaration', value };
|
|
924
|
+
if (options.locations) {
|
|
925
|
+
node.loc = location();
|
|
926
|
+
}
|
|
927
|
+
return node;
|
|
928
|
+
}, peg$c1581 = peg$otherExpectation("arrange declaration"), peg$currPos = 0, peg$savedPos = 0, peg$posDetailsCache = [{ line: 1, column: 1 }], peg$maxFailPos = 0, peg$maxFailExpected = [], peg$silentFails = 0, peg$result;
|
|
917
929
|
if ("startRule" in options) {
|
|
918
930
|
if (!(options.startRule in peg$startRuleFunctions)) {
|
|
919
931
|
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
|
|
@@ -20481,6 +20493,176 @@ function peg$parse(input, options) {
|
|
|
20481
20493
|
}
|
|
20482
20494
|
return s0;
|
|
20483
20495
|
}
|
|
20496
|
+
function peg$parseOArrangeDeclaration() {
|
|
20497
|
+
var s0, s1, s2, s3, s4, s5, s6;
|
|
20498
|
+
peg$silentFails++;
|
|
20499
|
+
s0 = peg$currPos;
|
|
20500
|
+
if (input.substr(peg$currPos, 8) === peg$c1574) {
|
|
20501
|
+
s1 = peg$c1574;
|
|
20502
|
+
peg$currPos += 8;
|
|
20503
|
+
}
|
|
20504
|
+
else {
|
|
20505
|
+
s1 = peg$FAILED;
|
|
20506
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
20507
|
+
peg$fail(peg$c1575);
|
|
20508
|
+
}
|
|
20509
|
+
}
|
|
20510
|
+
if (s1 !== peg$FAILED) {
|
|
20511
|
+
s2 = peg$parseWS();
|
|
20512
|
+
if (s2 === peg$FAILED) {
|
|
20513
|
+
s2 = null;
|
|
20514
|
+
}
|
|
20515
|
+
if (s2 !== peg$FAILED) {
|
|
20516
|
+
s3 = peg$parseLabelOrLabelList();
|
|
20517
|
+
if (s3 !== peg$FAILED) {
|
|
20518
|
+
s4 = peg$parseWS();
|
|
20519
|
+
if (s4 === peg$FAILED) {
|
|
20520
|
+
s4 = null;
|
|
20521
|
+
}
|
|
20522
|
+
if (s4 !== peg$FAILED) {
|
|
20523
|
+
if (input.charCodeAt(peg$currPos) === 59) {
|
|
20524
|
+
s5 = peg$c1213;
|
|
20525
|
+
peg$currPos++;
|
|
20526
|
+
}
|
|
20527
|
+
else {
|
|
20528
|
+
s5 = peg$FAILED;
|
|
20529
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
20530
|
+
peg$fail(peg$c1214);
|
|
20531
|
+
}
|
|
20532
|
+
}
|
|
20533
|
+
if (s5 !== peg$FAILED) {
|
|
20534
|
+
s6 = peg$parseWS();
|
|
20535
|
+
if (s6 === peg$FAILED) {
|
|
20536
|
+
s6 = null;
|
|
20537
|
+
}
|
|
20538
|
+
if (s6 !== peg$FAILED) {
|
|
20539
|
+
peg$savedPos = s0;
|
|
20540
|
+
s1 = peg$c1576(s3);
|
|
20541
|
+
s0 = s1;
|
|
20542
|
+
}
|
|
20543
|
+
else {
|
|
20544
|
+
peg$currPos = s0;
|
|
20545
|
+
s0 = peg$FAILED;
|
|
20546
|
+
}
|
|
20547
|
+
}
|
|
20548
|
+
else {
|
|
20549
|
+
peg$currPos = s0;
|
|
20550
|
+
s0 = peg$FAILED;
|
|
20551
|
+
}
|
|
20552
|
+
}
|
|
20553
|
+
else {
|
|
20554
|
+
peg$currPos = s0;
|
|
20555
|
+
s0 = peg$FAILED;
|
|
20556
|
+
}
|
|
20557
|
+
}
|
|
20558
|
+
else {
|
|
20559
|
+
peg$currPos = s0;
|
|
20560
|
+
s0 = peg$FAILED;
|
|
20561
|
+
}
|
|
20562
|
+
}
|
|
20563
|
+
else {
|
|
20564
|
+
peg$currPos = s0;
|
|
20565
|
+
s0 = peg$FAILED;
|
|
20566
|
+
}
|
|
20567
|
+
}
|
|
20568
|
+
else {
|
|
20569
|
+
peg$currPos = s0;
|
|
20570
|
+
s0 = peg$FAILED;
|
|
20571
|
+
}
|
|
20572
|
+
peg$silentFails--;
|
|
20573
|
+
if (s0 === peg$FAILED) {
|
|
20574
|
+
s1 = peg$FAILED;
|
|
20575
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
20576
|
+
peg$fail(peg$c1573);
|
|
20577
|
+
}
|
|
20578
|
+
}
|
|
20579
|
+
return s0;
|
|
20580
|
+
}
|
|
20581
|
+
function peg$parseFArrangeDeclaration() {
|
|
20582
|
+
var s0, s1, s2, s3, s4, s5, s6;
|
|
20583
|
+
peg$silentFails++;
|
|
20584
|
+
s0 = peg$currPos;
|
|
20585
|
+
if (input.substr(peg$currPos, 8) === peg$c1578) {
|
|
20586
|
+
s1 = peg$c1578;
|
|
20587
|
+
peg$currPos += 8;
|
|
20588
|
+
}
|
|
20589
|
+
else {
|
|
20590
|
+
s1 = peg$FAILED;
|
|
20591
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
20592
|
+
peg$fail(peg$c1579);
|
|
20593
|
+
}
|
|
20594
|
+
}
|
|
20595
|
+
if (s1 !== peg$FAILED) {
|
|
20596
|
+
s2 = peg$parseWS();
|
|
20597
|
+
if (s2 === peg$FAILED) {
|
|
20598
|
+
s2 = null;
|
|
20599
|
+
}
|
|
20600
|
+
if (s2 !== peg$FAILED) {
|
|
20601
|
+
s3 = peg$parseLabelOrLabelList();
|
|
20602
|
+
if (s3 !== peg$FAILED) {
|
|
20603
|
+
s4 = peg$parseWS();
|
|
20604
|
+
if (s4 === peg$FAILED) {
|
|
20605
|
+
s4 = null;
|
|
20606
|
+
}
|
|
20607
|
+
if (s4 !== peg$FAILED) {
|
|
20608
|
+
if (input.charCodeAt(peg$currPos) === 59) {
|
|
20609
|
+
s5 = peg$c1213;
|
|
20610
|
+
peg$currPos++;
|
|
20611
|
+
}
|
|
20612
|
+
else {
|
|
20613
|
+
s5 = peg$FAILED;
|
|
20614
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
20615
|
+
peg$fail(peg$c1214);
|
|
20616
|
+
}
|
|
20617
|
+
}
|
|
20618
|
+
if (s5 !== peg$FAILED) {
|
|
20619
|
+
s6 = peg$parseWS();
|
|
20620
|
+
if (s6 === peg$FAILED) {
|
|
20621
|
+
s6 = null;
|
|
20622
|
+
}
|
|
20623
|
+
if (s6 !== peg$FAILED) {
|
|
20624
|
+
peg$savedPos = s0;
|
|
20625
|
+
s1 = peg$c1580(s3);
|
|
20626
|
+
s0 = s1;
|
|
20627
|
+
}
|
|
20628
|
+
else {
|
|
20629
|
+
peg$currPos = s0;
|
|
20630
|
+
s0 = peg$FAILED;
|
|
20631
|
+
}
|
|
20632
|
+
}
|
|
20633
|
+
else {
|
|
20634
|
+
peg$currPos = s0;
|
|
20635
|
+
s0 = peg$FAILED;
|
|
20636
|
+
}
|
|
20637
|
+
}
|
|
20638
|
+
else {
|
|
20639
|
+
peg$currPos = s0;
|
|
20640
|
+
s0 = peg$FAILED;
|
|
20641
|
+
}
|
|
20642
|
+
}
|
|
20643
|
+
else {
|
|
20644
|
+
peg$currPos = s0;
|
|
20645
|
+
s0 = peg$FAILED;
|
|
20646
|
+
}
|
|
20647
|
+
}
|
|
20648
|
+
else {
|
|
20649
|
+
peg$currPos = s0;
|
|
20650
|
+
s0 = peg$FAILED;
|
|
20651
|
+
}
|
|
20652
|
+
}
|
|
20653
|
+
else {
|
|
20654
|
+
peg$currPos = s0;
|
|
20655
|
+
s0 = peg$FAILED;
|
|
20656
|
+
}
|
|
20657
|
+
peg$silentFails--;
|
|
20658
|
+
if (s0 === peg$FAILED) {
|
|
20659
|
+
s1 = peg$FAILED;
|
|
20660
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
20661
|
+
peg$fail(peg$c1577);
|
|
20662
|
+
}
|
|
20663
|
+
}
|
|
20664
|
+
return s0;
|
|
20665
|
+
}
|
|
20484
20666
|
function peg$parseArrangeDeclaration() {
|
|
20485
20667
|
var s0;
|
|
20486
20668
|
peg$silentFails++;
|
|
@@ -20488,13 +20670,19 @@ function peg$parse(input, options) {
|
|
|
20488
20670
|
if (s0 === peg$FAILED) {
|
|
20489
20671
|
s0 = peg$parseArrangeEndDeclaration();
|
|
20490
20672
|
if (s0 === peg$FAILED) {
|
|
20491
|
-
s0 = peg$
|
|
20673
|
+
s0 = peg$parseOArrangeDeclaration();
|
|
20674
|
+
if (s0 === peg$FAILED) {
|
|
20675
|
+
s0 = peg$parseFArrangeDeclaration();
|
|
20676
|
+
if (s0 === peg$FAILED) {
|
|
20677
|
+
s0 = peg$parseRegularArrangeDeclaration();
|
|
20678
|
+
}
|
|
20679
|
+
}
|
|
20492
20680
|
}
|
|
20493
20681
|
}
|
|
20494
20682
|
peg$silentFails--;
|
|
20495
20683
|
if (s0 === peg$FAILED) {
|
|
20496
20684
|
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
20497
|
-
peg$fail(peg$
|
|
20685
|
+
peg$fail(peg$c1581);
|
|
20498
20686
|
}
|
|
20499
20687
|
}
|
|
20500
20688
|
return s0;
|
|
@@ -22395,7 +22583,8 @@ function compile_rule_handler(rule) {
|
|
|
22395
22583
|
return { agg_as: 'state_declaration', val: { state: rule.name, declarations: rule.value } };
|
|
22396
22584
|
}
|
|
22397
22585
|
if (['arrange_declaration', 'arrange_start_declaration',
|
|
22398
|
-
'arrange_end_declaration'
|
|
22586
|
+
'arrange_end_declaration', 'oarrange_declaration',
|
|
22587
|
+
'farrange_declaration'].includes(rule.key)) {
|
|
22399
22588
|
return { agg_as: rule.key, val: [rule.value] };
|
|
22400
22589
|
}
|
|
22401
22590
|
// things that can only exist once and are just a value under their own name
|
|
@@ -22601,6 +22790,8 @@ function compile(tree) {
|
|
|
22601
22790
|
arrange_declaration: [],
|
|
22602
22791
|
arrange_start_declaration: [],
|
|
22603
22792
|
arrange_end_declaration: [],
|
|
22793
|
+
oarrange_declaration: [],
|
|
22794
|
+
farrange_declaration: [],
|
|
22604
22795
|
machine_version: [],
|
|
22605
22796
|
default_state_config: [],
|
|
22606
22797
|
default_active_state_config: [],
|
|
@@ -22726,6 +22917,7 @@ function compile(tree) {
|
|
|
22726
22917
|
}
|
|
22727
22918
|
});
|
|
22728
22919
|
['arrange_declaration', 'arrange_start_declaration', 'arrange_end_declaration',
|
|
22920
|
+
'oarrange_declaration', 'farrange_declaration',
|
|
22729
22921
|
'machine_author', 'machine_contributor', 'machine_reference', 'theme',
|
|
22730
22922
|
'state_declaration', 'property_definition', 'default_state_config',
|
|
22731
22923
|
'default_start_state_config', 'default_end_state_config',
|
|
@@ -23396,7 +23588,7 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
23396
23588
|
* Useful for runtime diagnostics and for embedding in serialized machine
|
|
23397
23589
|
* snapshots so that deserializers can detect version-skew.
|
|
23398
23590
|
*/
|
|
23399
|
-
const version = "5.
|
|
23591
|
+
const version = "5.154.0";
|
|
23400
23592
|
|
|
23401
23593
|
// whargarbl lots of these return arrays could/should be sets
|
|
23402
23594
|
const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
|
|
@@ -23711,9 +23903,13 @@ function find_connected_components(states, edges) {
|
|
|
23711
23903
|
}
|
|
23712
23904
|
return result;
|
|
23713
23905
|
}
|
|
23906
|
+
/** Default number of independent Monte-Carlo runs when none is declared. */
|
|
23907
|
+
const STOCHASTIC_DEFAULT_RUNS = 1000;
|
|
23908
|
+
/** Default per-run step cap (montecarlo) / walk length (steady_state). */
|
|
23909
|
+
const STOCHASTIC_DEFAULT_MAX_STEPS = 1000;
|
|
23714
23910
|
class Machine {
|
|
23715
23911
|
// whargarbl this badly needs to be broken up, monolith master
|
|
23716
|
-
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 = [], 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 }) {
|
|
23912
|
+
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 }) {
|
|
23717
23913
|
this._time_source = time_source !== null && time_source !== void 0 ? time_source : (() => new Date().getTime());
|
|
23718
23914
|
this._create_started = this._time_source();
|
|
23719
23915
|
this._instance_name = instance_name;
|
|
@@ -23750,6 +23946,8 @@ class Machine {
|
|
|
23750
23946
|
this._arrange_declaration = arrange_declaration;
|
|
23751
23947
|
this._arrange_start_declaration = arrange_start_declaration;
|
|
23752
23948
|
this._arrange_end_declaration = arrange_end_declaration;
|
|
23949
|
+
this._oarrange_declaration = oarrange_declaration;
|
|
23950
|
+
this._farrange_declaration = farrange_declaration;
|
|
23753
23951
|
this._dot_preamble = dot_preamble;
|
|
23754
23952
|
this._themes = theme;
|
|
23755
23953
|
this._flow = flow;
|
|
@@ -24162,11 +24360,11 @@ class Machine {
|
|
|
24162
24360
|
}
|
|
24163
24361
|
this._created = this._time_source();
|
|
24164
24362
|
this.auto_set_state_timeout();
|
|
24165
|
-
this._arrange_declaration.forEach((arrange_pair) => arrange_pair.forEach((possibleState) => {
|
|
24363
|
+
[this._arrange_declaration, this._oarrange_declaration, this._farrange_declaration].forEach((declaration) => declaration.forEach((arrange_pair) => arrange_pair.forEach((possibleState) => {
|
|
24166
24364
|
if (!(this._states.has(possibleState))) {
|
|
24167
24365
|
throw new JssmError(this, `Cannot arrange state that does not exist "${possibleState}"`);
|
|
24168
24366
|
}
|
|
24169
|
-
}));
|
|
24367
|
+
})));
|
|
24170
24368
|
}
|
|
24171
24369
|
/********
|
|
24172
24370
|
*
|
|
@@ -24371,13 +24569,13 @@ class Machine {
|
|
|
24371
24569
|
* `;
|
|
24372
24570
|
*
|
|
24373
24571
|
* traffic_light.state(); // Off
|
|
24374
|
-
* traffic_light.props(); // { can_go: true, hesitate: true, stop_first: true
|
|
24572
|
+
* traffic_light.props(); // { can_go: true, hesitate: true, stop_first: true }
|
|
24375
24573
|
*
|
|
24376
24574
|
* traffic_light.go('Red');
|
|
24377
|
-
* traffic_light.props(); // { can_go: false, hesitate: true, stop_first: true
|
|
24575
|
+
* traffic_light.props(); // { can_go: false, hesitate: true, stop_first: true }
|
|
24378
24576
|
*
|
|
24379
24577
|
* traffic_light.go('Green');
|
|
24380
|
-
* traffic_light.props(); // { can_go: true, hesitate: false, stop_first: false
|
|
24578
|
+
* traffic_light.props(); // { can_go: true, hesitate: false, stop_first: false }
|
|
24381
24579
|
* ```
|
|
24382
24580
|
*
|
|
24383
24581
|
* @returns An object mapping every known property name to its current value
|
|
@@ -25225,6 +25423,147 @@ class Machine {
|
|
|
25225
25423
|
probabilistic_histo_walk(n) {
|
|
25226
25424
|
return histograph(this.probabilistic_walk(n));
|
|
25227
25425
|
}
|
|
25426
|
+
/** One non-destructive weighted-random walk over the graph from `start`.
|
|
25427
|
+
*
|
|
25428
|
+
* Reads the graph and advances the PRNG only — it never calls
|
|
25429
|
+
* {@link Machine.transition}, so it fires no hooks, mutates no machine
|
|
25430
|
+
* state, and touches no `data`. A state with no probabilistic exits
|
|
25431
|
+
* (a terminal, or a forced-only `~>` state) ends the walk.
|
|
25432
|
+
*
|
|
25433
|
+
* @param start - State to begin the walk from.
|
|
25434
|
+
* @param max_steps - Maximum transitions before the walk is step-capped.
|
|
25435
|
+
* @returns The {@link JssmStochasticRun} for this walk.
|
|
25436
|
+
*/
|
|
25437
|
+
_stochastic_one_walk(start, max_steps) {
|
|
25438
|
+
const states = [start];
|
|
25439
|
+
const edges = [];
|
|
25440
|
+
let cur = start;
|
|
25441
|
+
let terminated = false;
|
|
25442
|
+
for (let step = 0; step < max_steps; step++) {
|
|
25443
|
+
const exits = this.probable_exits_for(cur);
|
|
25444
|
+
if (exits.length === 0) {
|
|
25445
|
+
terminated = true;
|
|
25446
|
+
break;
|
|
25447
|
+
}
|
|
25448
|
+
const selected = weighted_rand_select(exits, undefined, this._rng);
|
|
25449
|
+
edges.push(`${cur}→${selected.to}`);
|
|
25450
|
+
cur = selected.to;
|
|
25451
|
+
states.push(cur);
|
|
25452
|
+
}
|
|
25453
|
+
return { states, edges, length: states.length - 1, terminated };
|
|
25454
|
+
}
|
|
25455
|
+
/** Lazily yield one {@link JssmStochasticRun} at a time.
|
|
25456
|
+
*
|
|
25457
|
+
* In `montecarlo` mode (default) yields `runs` independent walks from the
|
|
25458
|
+
* current state, each ending at a terminal or after `max_steps`. In
|
|
25459
|
+
* `steady_state` mode yields exactly one walk of `max_steps` steps. This
|
|
25460
|
+
* is the lazy engine behind {@link Machine.stochastic_summary}; the
|
|
25461
|
+
* fsl-stochastic panel drives it across animation frames.
|
|
25462
|
+
*
|
|
25463
|
+
* Passing `seed` reseeds the machine for reproducible runs. Unlike
|
|
25464
|
+
* {@link Machine.stochastic_summary}, the generator does NOT restore the
|
|
25465
|
+
* prior seed afterward — a direct caller's machine is left reseeded.
|
|
25466
|
+
*
|
|
25467
|
+
* @param opts - {@link JssmStochasticOptions}.
|
|
25468
|
+
* @returns A generator of per-run results.
|
|
25469
|
+
*
|
|
25470
|
+
* @example
|
|
25471
|
+
* const m = sm`a 'go' -> b 'go' -> c;`;
|
|
25472
|
+
* [...m.stochastic_runs({ runs: 2, seed: 1 })].length; // => 2
|
|
25473
|
+
*/
|
|
25474
|
+
*stochastic_runs(opts = {}) {
|
|
25475
|
+
var _a, _b, _c, _d, _e;
|
|
25476
|
+
if (opts.seed !== undefined) {
|
|
25477
|
+
this.rng_seed = opts.seed;
|
|
25478
|
+
}
|
|
25479
|
+
const mode = (_a = opts.mode) !== null && _a !== void 0 ? _a : 'montecarlo';
|
|
25480
|
+
const max_steps = (_b = opts.max_steps) !== null && _b !== void 0 ? _b : STOCHASTIC_DEFAULT_MAX_STEPS;
|
|
25481
|
+
const runs = (mode === 'steady_state')
|
|
25482
|
+
? 1
|
|
25483
|
+
: ((_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);
|
|
25484
|
+
const start = this.state();
|
|
25485
|
+
for (let i = 0; i < runs; i++) {
|
|
25486
|
+
yield this._stochastic_one_walk(start, max_steps);
|
|
25487
|
+
}
|
|
25488
|
+
}
|
|
25489
|
+
/** Run many weighted-random walks and return aggregate statistics.
|
|
25490
|
+
*
|
|
25491
|
+
* Honors `%` transition probabilities (via the existing probabilistic
|
|
25492
|
+
* machinery). Non-destructive: the machine's current state and
|
|
25493
|
+
* {@link Machine.rng_seed} are restored before returning, so calling this
|
|
25494
|
+
* never perturbs the live machine. `montecarlo` mode (default) reports
|
|
25495
|
+
* per-run `path_lengths`, `terminal_reached`, and `capped`; `steady_state`
|
|
25496
|
+
* mode runs one long walk and omits those fields.
|
|
25497
|
+
*
|
|
25498
|
+
* Timing (`after`) decorations and data-guard conditions are not modeled
|
|
25499
|
+
* by this sampler; it walks the probabilistic graph topology.
|
|
25500
|
+
*
|
|
25501
|
+
* @param opts - {@link JssmStochasticOptions}. `runs` defaults to the
|
|
25502
|
+
* machine's declared `editor: { stochastic_run_count }` (fsl#1334) when
|
|
25503
|
+
* present, otherwise {@link STOCHASTIC_DEFAULT_RUNS}.
|
|
25504
|
+
* @returns A {@link JssmStochasticSummary}.
|
|
25505
|
+
*
|
|
25506
|
+
* @see Machine.stochastic_runs
|
|
25507
|
+
* @see Machine.probabilistic_walk
|
|
25508
|
+
* @see Machine.editor_config
|
|
25509
|
+
*
|
|
25510
|
+
* @example
|
|
25511
|
+
* const m = sm`a 'go' -> b 'go' -> c;`;
|
|
25512
|
+
* const s = m.stochastic_summary({ runs: 100, seed: 1 });
|
|
25513
|
+
* s.terminal_reached; // => 100
|
|
25514
|
+
*/
|
|
25515
|
+
stochastic_summary(opts = {}) {
|
|
25516
|
+
var _a, _b, _c;
|
|
25517
|
+
const mode = (_a = opts.mode) !== null && _a !== void 0 ? _a : 'montecarlo';
|
|
25518
|
+
const saved_seed = this._rng_seed;
|
|
25519
|
+
if (opts.seed !== undefined) {
|
|
25520
|
+
this.rng_seed = opts.seed;
|
|
25521
|
+
}
|
|
25522
|
+
const effective_seed = this._rng_seed;
|
|
25523
|
+
const state_visits = new Map();
|
|
25524
|
+
const edge_traversals = new Map();
|
|
25525
|
+
const path_lengths = [];
|
|
25526
|
+
let terminal_reached = 0, capped = 0, runs = 0;
|
|
25527
|
+
try {
|
|
25528
|
+
for (const run of this.stochastic_runs(Object.assign(Object.assign({}, opts), { mode }))) {
|
|
25529
|
+
runs += 1;
|
|
25530
|
+
for (const s of run.states) {
|
|
25531
|
+
state_visits.set(s, ((_b = state_visits.get(s)) !== null && _b !== void 0 ? _b : 0) + 1);
|
|
25532
|
+
}
|
|
25533
|
+
for (const e of run.edges) {
|
|
25534
|
+
edge_traversals.set(e, ((_c = edge_traversals.get(e)) !== null && _c !== void 0 ? _c : 0) + 1);
|
|
25535
|
+
}
|
|
25536
|
+
if (mode === 'montecarlo') {
|
|
25537
|
+
if (run.terminated) {
|
|
25538
|
+
terminal_reached += 1;
|
|
25539
|
+
path_lengths.push(run.length);
|
|
25540
|
+
}
|
|
25541
|
+
else {
|
|
25542
|
+
capped += 1;
|
|
25543
|
+
}
|
|
25544
|
+
}
|
|
25545
|
+
}
|
|
25546
|
+
}
|
|
25547
|
+
finally {
|
|
25548
|
+
// restore the PRNG so the call is non-destructive even when the loop throws
|
|
25549
|
+
this.rng_seed = saved_seed;
|
|
25550
|
+
}
|
|
25551
|
+
const total_visits = [...state_visits.values()].reduce((a, b) => a + b, 0);
|
|
25552
|
+
const state_visit_fraction = new Map();
|
|
25553
|
+
for (const [s, c] of state_visits) {
|
|
25554
|
+
state_visit_fraction.set(s, c / total_visits);
|
|
25555
|
+
}
|
|
25556
|
+
const summary = {
|
|
25557
|
+
mode, runs, seed: effective_seed,
|
|
25558
|
+
state_visits, state_visit_fraction, edge_traversals,
|
|
25559
|
+
};
|
|
25560
|
+
if (mode === 'montecarlo') {
|
|
25561
|
+
summary.path_lengths = path_lengths;
|
|
25562
|
+
summary.terminal_reached = terminal_reached;
|
|
25563
|
+
summary.capped = capped;
|
|
25564
|
+
}
|
|
25565
|
+
return summary;
|
|
25566
|
+
}
|
|
25228
25567
|
/********
|
|
25229
25568
|
*
|
|
25230
25569
|
* List all actions available from this state. Please note that the order of
|
|
@@ -29164,6 +29503,11 @@ function colored_label(tr, which, color) {
|
|
|
29164
29503
|
function states_to_edges_string(u_jssm, l_states, state_index, state_kinds) {
|
|
29165
29504
|
const strike = new Set();
|
|
29166
29505
|
const kind_of = (s) => { var _a; return (_a = state_kinds.get(s)) !== null && _a !== void 0 ? _a : 'base'; };
|
|
29506
|
+
// `farrange` forces its members' left-to-right order by relaxing the rank
|
|
29507
|
+
// constraint of every real edge incident to a member, so the invisible
|
|
29508
|
+
// ordering chain (emitted in arranges_for) wins over the members' own edges.
|
|
29509
|
+
const farrange_members = new Set((u_jssm._farrange_declaration || []).flat().map(String));
|
|
29510
|
+
const cf = (s, ex) => (farrange_members.has(String(s)) || farrange_members.has(String(ex))) ? 'constraint=false;' : '';
|
|
29167
29511
|
// Render one solo directed edge `s -> ex` for transition `tr`.
|
|
29168
29512
|
const solo_edge = (s, ex, tr) => {
|
|
29169
29513
|
const ex_kind = kind_of(ex);
|
|
@@ -29173,7 +29517,7 @@ function states_to_edges_string(u_jssm, l_states, state_index, state_kinds) {
|
|
|
29173
29517
|
const maybeLabel = label ? `taillabel="${doublequote(label)}";` : '';
|
|
29174
29518
|
const arrowHead = arrow_for(tr);
|
|
29175
29519
|
const edgeInline = `${maybeLabel}arrowhead=${arrowHead};color="${line_color(ex_kind, tr.kind, '_solo')}"`;
|
|
29176
|
-
return `${node_of(s, state_index)}->${node_of(ex, state_index)} [${labelInline}${edgeInline}];`;
|
|
29520
|
+
return `${node_of(s, state_index)}->${node_of(ex, state_index)} [${cf(s, ex)}${labelInline}${edgeInline}];`;
|
|
29177
29521
|
};
|
|
29178
29522
|
return l_states.map((s) => u_jssm.list_exits(s).map((ex) => {
|
|
29179
29523
|
if (strike.has(`${s}|${ex}`)) {
|
|
@@ -29207,7 +29551,7 @@ function states_to_edges_string(u_jssm, l_states, state_index, state_kinds) {
|
|
|
29207
29551
|
const arrowTail = arrow_for(pair_tr);
|
|
29208
29552
|
const edgeInline = `${maybeLabel}${maybeRLabel}arrowhead=${arrowHead};arrowtail=${arrowTail};dir=both;color="${line_color(ex_kind, edge_tr.kind, '_1')}:${line_color(s_kind, pair_tr.kind, '_2')}"`;
|
|
29209
29553
|
strike.add(`${ex}|${s}`);
|
|
29210
|
-
return `${node_of(s, state_index)}->${node_of(ex, state_index)} [${labelInline}${edgeInline}];`;
|
|
29554
|
+
return `${node_of(s, state_index)}->${node_of(ex, state_index)} [${cf(s, ex)}${labelInline}${edgeInline}];`;
|
|
29211
29555
|
}
|
|
29212
29556
|
// one directed line per forward edge — parallel action edges (#325) and
|
|
29213
29557
|
// self-loops (#531) draw each transition separately. The reverse edges,
|
|
@@ -29216,8 +29560,15 @@ function states_to_edges_string(u_jssm, l_states, state_index, state_kinds) {
|
|
|
29216
29560
|
}).join(' ')).join(' ');
|
|
29217
29561
|
}
|
|
29218
29562
|
/**
|
|
29219
|
-
* Render `arrange`, `arrange_start`,
|
|
29220
|
-
* rank-grouped subgraphs (`rank=same`/`rank=min`/`rank=max`).
|
|
29563
|
+
* Render `arrange`, `arrange_start`, `arrange_end`, `oarrange`, and `farrange`
|
|
29564
|
+
* declarations to rank-grouped subgraphs (`rank=same`/`rank=min`/`rank=max`).
|
|
29565
|
+
*
|
|
29566
|
+
* `arrange*` emit only a rank group. `oarrange`/`farrange` additionally emit an
|
|
29567
|
+
* invisible left-to-right ordering chain (`a->b->c [style=invis]`) so the listed
|
|
29568
|
+
* states keep their written order on the rank. `oarrange` is best-effort (it
|
|
29569
|
+
* yields to hard rank constraints, never reshaping the graph); `farrange`'s
|
|
29570
|
+
* ordering is forced by also relaxing its members' real edges via
|
|
29571
|
+
* `constraint=false`, emitted in {@link states_to_edges_string}.
|
|
29221
29572
|
*
|
|
29222
29573
|
* @internal
|
|
29223
29574
|
*/
|
|
@@ -29225,9 +29576,16 @@ function arranges_for(u_jssm, state_index) {
|
|
|
29225
29576
|
const group = (decls, rank) => decls
|
|
29226
29577
|
? decls.map(d => `{rank=${rank}; ${d.map(di => node_of(di, state_index)).join('; ')};};`).join('\n')
|
|
29227
29578
|
: '';
|
|
29579
|
+
// For each group, an invisible chain pinning left-to-right order: one
|
|
29580
|
+
// `prev->cur [style=invis]` edge per adjacent pair (empty for <2 members).
|
|
29581
|
+
const order_chain = (decls) => decls
|
|
29582
|
+
? decls.map(d => d.slice(1).map((di, i) => `${node_of(d[i], state_index)}->${node_of(di, state_index)} [style=invis];`).join(' ')).join('\n')
|
|
29583
|
+
: '';
|
|
29228
29584
|
return group(u_jssm._arrange_declaration, 'same')
|
|
29229
29585
|
+ group(u_jssm._arrange_start_declaration, 'min')
|
|
29230
|
-
+ group(u_jssm._arrange_end_declaration, 'max')
|
|
29586
|
+
+ group(u_jssm._arrange_end_declaration, 'max')
|
|
29587
|
+
+ group(u_jssm._oarrange_declaration, 'same') + order_chain(u_jssm._oarrange_declaration)
|
|
29588
|
+
+ group(u_jssm._farrange_declaration, 'same') + order_chain(u_jssm._farrange_declaration);
|
|
29231
29589
|
}
|
|
29232
29590
|
/**
|
|
29233
29591
|
* Slugify a group name into the body of a Graphviz `cluster_…` subgraph
|