linny-r 1.1.22 → 1.1.23
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/package.json
CHANGED
package/static/index.html
CHANGED
@@ -1404,7 +1404,7 @@ and move the cursor over the status bar">
|
|
1404
1404
|
<option value="1">Product</option>
|
1405
1405
|
<option value="2">Cluster</option>
|
1406
1406
|
<option value="3">Link</option>
|
1407
|
-
<option value="4">Constraint</option>
|
1407
|
+
<!-- <option value="4">Constraint</option> -->
|
1408
1408
|
<option value="5">Actor</option>
|
1409
1409
|
<option value="6">Dataset</option>
|
1410
1410
|
<option value="7">Equation</option>
|
@@ -1820,7 +1820,7 @@ NOTE: * and ? will be interpreted as wildcards"
|
|
1820
1820
|
<option value="1">Product</option>
|
1821
1821
|
<option value="2">Cluster</option>
|
1822
1822
|
<option value="3">Link</option>
|
1823
|
-
<option value="4">Constraint</option>
|
1823
|
+
<!-- <option value="4">Constraint</option> -->
|
1824
1824
|
<option value="5">Actor</option>
|
1825
1825
|
<option value="6">Dataset</option>
|
1826
1826
|
<option value="7">Equation</option>
|
@@ -1957,7 +1957,7 @@ NOTE: * and ? will be interpreted as wildcards"
|
|
1957
1957
|
<option value="1">Product</option>
|
1958
1958
|
<option id="add-sa-variable-cluster" value="2">Cluster</option>
|
1959
1959
|
<option value="3">Link</option>
|
1960
|
-
<option value="4">Constraint</option>
|
1960
|
+
<!-- <option value="4">Constraint</option> -->
|
1961
1961
|
<option value="5">Actor</option>
|
1962
1962
|
<option value="6">Dataset</option>
|
1963
1963
|
<option id="add-sa-variable-equation" value="7">Equation</option>
|
@@ -738,8 +738,11 @@ class SensitivityAnalysis {
|
|
738
738
|
oax = (obj ? obj.attributeExpression(vn[1]) : null);
|
739
739
|
if(oax) {
|
740
740
|
this.parameters.push(oax);
|
741
|
+
} else if(vn.length === 1 && obj instanceof Dataset) {
|
742
|
+
// Dataset without selector => push the dataset vector
|
743
|
+
this.parameters.push(obj.vector);
|
741
744
|
} else {
|
742
|
-
UI.alert(`Parameter ${p} is not
|
745
|
+
UI.alert(`Parameter ${p} is not a dataset or expression`);
|
743
746
|
}
|
744
747
|
}
|
745
748
|
this.chart = new Chart(this.chart_title);
|
@@ -841,6 +844,7 @@ class SensitivityAnalysis {
|
|
841
844
|
VM.halt();
|
842
845
|
this.readyButtons();
|
843
846
|
this.showProgress('');
|
847
|
+
this.must_pause = false;
|
844
848
|
}
|
845
849
|
|
846
850
|
clearResults() {
|
@@ -10513,7 +10513,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
10513
10513
|
this.base_selectors.addEventListener(
|
10514
10514
|
'blur', () => SENSITIVITY_ANALYSIS.setBaseSelectors());
|
10515
10515
|
|
10516
|
-
this.delta = document.getElementById('
|
10516
|
+
this.delta = document.getElementById('sensitivity-delta');
|
10517
10517
|
this.delta.addEventListener(
|
10518
10518
|
'focus', () => SENSITIVITY_ANALYSIS.editDelta());
|
10519
10519
|
this.delta.addEventListener(
|
@@ -10610,6 +10610,8 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
10610
10610
|
}
|
10611
10611
|
|
10612
10612
|
updateControlPanel() {
|
10613
|
+
// Shows the control panel, or when the analysis is running the
|
10614
|
+
// legend to the outcomes (also to prevent changes to parameters)
|
10613
10615
|
this.base_selectors.value = MODEL.base_case_selectors;
|
10614
10616
|
this.delta.value = VM.sig4Dig(MODEL.sensitivity_delta);
|
10615
10617
|
const tr = [];
|
@@ -10900,6 +10902,8 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
10900
10902
|
// NOTE: clusters have no suitable attributes, and equations are endogenous
|
10901
10903
|
md.element('cluster').style.display = 'none';
|
10902
10904
|
md.element('equation').style.display = 'none';
|
10905
|
+
// NOTE: update to ensure that valid attributes are selectable
|
10906
|
+
X_EDIT.updateVariableBar('add-sa-');
|
10903
10907
|
md.show();
|
10904
10908
|
}
|
10905
10909
|
|
@@ -10909,6 +10913,8 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
10909
10913
|
md.element('type').innerText = 'outcome';
|
10910
10914
|
md.element('cluster').style.display = 'block';
|
10911
10915
|
md.element('equation').style.display = 'block';
|
10916
|
+
// NOTE: update to ensure that valid attributes are selectable
|
10917
|
+
X_EDIT.updateVariableBar('add-sa-');
|
10912
10918
|
md.show();
|
10913
10919
|
}
|
10914
10920
|
|
@@ -10977,9 +10983,14 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
10977
10983
|
a = md.selectedOption('attr').text;
|
10978
10984
|
let n = '';
|
10979
10985
|
if(e === 'Equation' && a) {
|
10986
|
+
// For equations, the attribute denotes the name
|
10980
10987
|
n = a;
|
10981
10988
|
} else if(o && a) {
|
10989
|
+
// Most variables are defined by name + attribute ...
|
10982
10990
|
n = o + UI.OA_SEPARATOR + a;
|
10991
|
+
} else if(e === 'Dataset' && o) {
|
10992
|
+
// ... but for datasets the selector is optional
|
10993
|
+
n = o;
|
10983
10994
|
}
|
10984
10995
|
if(n) {
|
10985
10996
|
if(t === 'parameter' && MODEL.sensitivity_parameters.indexOf(n) < 0) {
|
@@ -11021,6 +11032,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
11021
11032
|
this.start_btn.classList.add('off');
|
11022
11033
|
this.pause_btn.classList.remove('off');
|
11023
11034
|
this.stop_btn.classList.add('off');
|
11035
|
+
this.must_pause = false;
|
11024
11036
|
return paused;
|
11025
11037
|
}
|
11026
11038
|
|
@@ -11029,6 +11041,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
11029
11041
|
this.pause_btn.classList.add('off');
|
11030
11042
|
this.stop_btn.classList.add('off');
|
11031
11043
|
this.start_btn.classList.remove('off', 'blink');
|
11044
|
+
this.must_pause = false;
|
11032
11045
|
}
|
11033
11046
|
|
11034
11047
|
pausedButtons(aci) {
|
@@ -11047,6 +11060,8 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
11047
11060
|
this.readyButtons();
|
11048
11061
|
this.reset_btn.classList.add('off');
|
11049
11062
|
this.selected_run = -1;
|
11063
|
+
this.must_pause = false;
|
11064
|
+
this.progress.innerHTML = '';
|
11050
11065
|
this.updateDialog();
|
11051
11066
|
}
|
11052
11067
|
|
@@ -11802,6 +11817,32 @@ class GUIExperimentManager extends ExperimentManager {
|
|
11802
11817
|
}
|
11803
11818
|
}
|
11804
11819
|
|
11820
|
+
toggleChartRow(r, n, shift) {
|
11821
|
+
// Toggle `n` consecutive rows, starting at row `r` (0 = top), to be
|
11822
|
+
// (no longer) part of the chart combination set
|
11823
|
+
const
|
11824
|
+
x = this.selected_experiment,
|
11825
|
+
// Let `n` be the number of the first run on row `r`
|
11826
|
+
nconf = r * this.nr_of_configurations;
|
11827
|
+
if(x && r < x.combinations.length / this.nr_of_configurations) {
|
11828
|
+
// NOTE: first cell of row determines ADD or REMOVE
|
11829
|
+
const add = x.chart_combinations.indexOf(n) < 0;
|
11830
|
+
for(let i = 0; i < this.nr_of_configurations; i++) {
|
11831
|
+
const ic = x.chart_combinations.indexOf(i);
|
11832
|
+
if(add) {
|
11833
|
+
if(ic < 0) x.chart_combinations.push(nconf + i);
|
11834
|
+
} else {
|
11835
|
+
if(!add) x.chart_combinations.splice(nconf + i, 1);
|
11836
|
+
}
|
11837
|
+
}
|
11838
|
+
this.updateData();
|
11839
|
+
}
|
11840
|
+
}
|
11841
|
+
|
11842
|
+
toggleChartColumn(c, shift) {
|
11843
|
+
// Toggle column `c` (0 = leftmost) to be part of the chart combination set
|
11844
|
+
}
|
11845
|
+
|
11805
11846
|
toggleChartCombi(n, shift, alt) {
|
11806
11847
|
// Set `n` to be the chart combination, or toggle if Shift-key is pressed,
|
11807
11848
|
// or execute single run if Alt-key is pressed
|
@@ -12788,7 +12829,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
12788
12829
|
md.element('separator').value = ds.separator;
|
12789
12830
|
md.element('quotes').value = ds.quotes;
|
12790
12831
|
md.element('precision').value = ds.precision;
|
12791
|
-
md.element('var-count').innerText = x.
|
12832
|
+
md.element('var-count').innerText = x.runs[0].results.length;
|
12792
12833
|
md.element('run-count').innerText = runs;
|
12793
12834
|
md.element('run-s').innerText = (sruns === 1 ? '' : 's');
|
12794
12835
|
}
|
@@ -2485,12 +2485,15 @@ class LinnyRModel {
|
|
2485
2485
|
const ds_dict = {};
|
2486
2486
|
for(let k in this.datasets) if(this.datasets.hasOwnProperty(k)) {
|
2487
2487
|
const ds = this.datasets[k];
|
2488
|
-
|
2489
|
-
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
|
2488
|
+
// NOTE: ignore selectors of the equations dataset
|
2489
|
+
if(ds !== this.equations_dataset) {
|
2490
|
+
for(let m in ds.modifiers) if(ds.modifiers.hasOwnProperty(m)) {
|
2491
|
+
const s = ds.modifiers[m].selector;
|
2492
|
+
if(s in ds_dict) {
|
2493
|
+
ds_dict[s].push(ds);
|
2494
|
+
} else {
|
2495
|
+
ds_dict[s] = [ds];
|
2496
|
+
}
|
2494
2497
|
}
|
2495
2498
|
}
|
2496
2499
|
}
|
@@ -7644,9 +7647,11 @@ class Dataset {
|
|
7644
7647
|
attributeExpression(a) {
|
7645
7648
|
// Returns expression for selector `a`, or NULL if no such selector exists
|
7646
7649
|
// NOTE: selectors no longer are case-sensitive
|
7647
|
-
|
7648
|
-
|
7649
|
-
|
7650
|
+
if(a) {
|
7651
|
+
a = UI.nameToID(a);
|
7652
|
+
for(let m in this.modifiers) if(this.modifiers.hasOwnProperty(m)) {
|
7653
|
+
if(m === a) return this.modifiers[m].expression;
|
7654
|
+
}
|
7650
7655
|
}
|
7651
7656
|
return null;
|
7652
7657
|
}
|
@@ -9226,7 +9231,12 @@ class ExperimentRunResult {
|
|
9226
9231
|
obj = MODEL.objectByID(this.object_id),
|
9227
9232
|
dn = obj.displayName;
|
9228
9233
|
// NOTE: for equations dataset, only display the modifier selector
|
9229
|
-
if(obj === MODEL.equations_dataset)
|
9234
|
+
if(obj === MODEL.equations_dataset) {
|
9235
|
+
const m = obj.modifiers[this.attribute.toLowerCase()];
|
9236
|
+
if(m) return m.selector;
|
9237
|
+
console.log('WARNING: Run result of non-existent equation', this.attribute);
|
9238
|
+
return this.attribute;
|
9239
|
+
}
|
9230
9240
|
return (this.attribute ? dn + '|' + this.attribute : dn);
|
9231
9241
|
}
|
9232
9242
|
|
@@ -9994,7 +10004,19 @@ class Experiment {
|
|
9994
10004
|
|
9995
10005
|
get resultsAsCSV() {
|
9996
10006
|
// Return results as specfied by the download settings
|
10007
|
+
// NOTE: no runs => no results => return empty string
|
10008
|
+
if(this.runs.length === 0) return '';
|
9997
10009
|
const
|
10010
|
+
// Local function to convert number to string
|
10011
|
+
numval = (v, p) => {
|
10012
|
+
// Return 0 as single digit
|
10013
|
+
if(Math.abs(v) < VM.NEAR_ZERO) return '0';
|
10014
|
+
// Return empty string for undefined or exceptional values
|
10015
|
+
if(!v || v < VM.MINUS_INFINITY || v > VM.PLUS_INFINITY) return '';
|
10016
|
+
// Return other values as float with specified precision
|
10017
|
+
return v.toPrecision(p);
|
10018
|
+
},
|
10019
|
+
prec = this.download_settings.precision,
|
9998
10020
|
allruns = this.download_settings.runs === 'all',
|
9999
10021
|
sep = (this.download_settings.separator === 'tab' ? '\t' :
|
10000
10022
|
(this.download_settings.separator === 'comma' ? ',' : ';')),
|
@@ -10019,24 +10041,21 @@ class Experiment {
|
|
10019
10041
|
exceptions: `${quo}Exceptions${quo}${sep}`,
|
10020
10042
|
run: []
|
10021
10043
|
};
|
10022
|
-
// Make list of indices of variables to include
|
10023
|
-
if(this.download_settings.variables === 'selected') {
|
10024
|
-
// Only one variable
|
10025
|
-
vars.push(this.resultIndex(this.selected_variable));
|
10026
|
-
} else {
|
10027
|
-
// All variables
|
10028
|
-
for(let i = 0; i < this.variables.length; i++) {
|
10029
|
-
vars.push(i);
|
10030
|
-
}
|
10031
|
-
}
|
10032
|
-
const nvars = vars.length;
|
10033
10044
|
for(let i = 0; i < this.combinations.length; i++) {
|
10034
10045
|
if(i < this.runs.length &&
|
10035
10046
|
(allruns || this.chart_combinations.indexOf(i) >= 0)) {
|
10036
10047
|
data.run.push(i);
|
10037
10048
|
}
|
10038
10049
|
}
|
10039
|
-
let series_length = 0
|
10050
|
+
let series_length = 0,
|
10051
|
+
// By default, assume all variables to be output
|
10052
|
+
start = 0,
|
10053
|
+
stop = this.runs[0].results.length;
|
10054
|
+
if(this.download_settings.variables === 'selected') {
|
10055
|
+
// Only one variable
|
10056
|
+
start = this.resultIndex(this.selected_variable);
|
10057
|
+
stop = start + 1;
|
10058
|
+
}
|
10040
10059
|
for(let i = 0; i < data.run.length; i++) {
|
10041
10060
|
const
|
10042
10061
|
rnr = data.run[i],
|
@@ -10044,31 +10063,35 @@ class Experiment {
|
|
10044
10063
|
data.nr += r.number;
|
10045
10064
|
data.combi += quo + this.combinations[rnr].join('|') + quo;
|
10046
10065
|
// Run duration in seconds
|
10047
|
-
data.rsecs +=
|
10048
|
-
data.ssecs +=
|
10066
|
+
data.rsecs += numval((r.time_recorded - r.time_started) * 0.001, 4);
|
10067
|
+
data.ssecs += numval(r.solver_seconds, 4);
|
10049
10068
|
data.warnings += r.warning_count;
|
10050
|
-
for(let j =
|
10069
|
+
for(let j = start; j < stop; j++) {
|
10051
10070
|
// Add empty cells for run attributes
|
10052
10071
|
data.nr += sep;
|
10053
10072
|
data.combi += sep;
|
10054
10073
|
data.rsecs += sep;
|
10055
10074
|
data.ssecs += sep;
|
10056
10075
|
data.warnings += sep;
|
10057
|
-
const rr = r.results[
|
10058
|
-
|
10059
|
-
|
10060
|
-
|
10061
|
-
|
10062
|
-
|
10063
|
-
|
10064
|
-
|
10065
|
-
|
10066
|
-
|
10067
|
-
|
10068
|
-
|
10069
|
-
|
10070
|
-
|
10071
|
-
|
10076
|
+
const rr = r.results[j];
|
10077
|
+
if(rr) {
|
10078
|
+
data.variable += rr.displayName + sep;
|
10079
|
+
// Series may differ in length; the longest determines the
|
10080
|
+
// number of rows of series data to be added
|
10081
|
+
series_length = Math.max(series_length, rr.vector.length);
|
10082
|
+
if(this.download_settings.statistics) {
|
10083
|
+
data.N += rr.N + sep;
|
10084
|
+
data.sum += numval(rr.sum, prec) + sep;
|
10085
|
+
data.mean += numval(rr.mean, prec) + sep;
|
10086
|
+
data.variance += numval(rr.variance, prec) + sep;
|
10087
|
+
data.minimum += numval(rr.minimum, prec) + sep;
|
10088
|
+
data.maximum += numval(rr.maximum, prec) + sep;
|
10089
|
+
data.NZ += rr.non_zero_tally + sep;
|
10090
|
+
data.last += numval(rr.last, prec) + sep;
|
10091
|
+
data.exceptions += rr.exceptions + sep;
|
10092
|
+
}
|
10093
|
+
} else {
|
10094
|
+
console.log('No run results for ', this.variables[vars[j]].displayName);
|
10072
10095
|
}
|
10073
10096
|
}
|
10074
10097
|
}
|
@@ -10084,20 +10107,18 @@ class Experiment {
|
|
10084
10107
|
}
|
10085
10108
|
if(this.download_settings.series) {
|
10086
10109
|
ds.push('t');
|
10087
|
-
const
|
10088
|
-
prec = this.download_settings.precision,
|
10089
|
-
row = [];
|
10110
|
+
const row = [];
|
10090
10111
|
for(let i = 0; i < series_length; i++) {
|
10091
10112
|
row.length = 0;
|
10092
10113
|
row.push(i);
|
10093
10114
|
for(let j = 0; j < data.run.length; j++) {
|
10094
10115
|
const rnr = data.run[j];
|
10095
|
-
for(let k =
|
10096
|
-
const rr = this.runs[rnr].results[
|
10097
|
-
if(
|
10098
|
-
|
10099
|
-
if(
|
10100
|
-
row.push(
|
10116
|
+
for(let k = start; k < stop; k++) {
|
10117
|
+
const rr = this.runs[rnr].results[k];
|
10118
|
+
if(rr) {
|
10119
|
+
// NOTE: only experiment variables have vector data
|
10120
|
+
if(rr.x_variable && i <= rr.N) {
|
10121
|
+
row.push(numval(rr.vector[i], prec));
|
10101
10122
|
} else {
|
10102
10123
|
row.push('');
|
10103
10124
|
}
|
@@ -305,7 +305,6 @@ class Expression {
|
|
305
305
|
// Pop the time step
|
306
306
|
this.step.pop();
|
307
307
|
this.trace('--STOP: ' + this.variableName);
|
308
|
-
DEBUGGING = false;
|
309
308
|
// Clear context for #
|
310
309
|
this.wildcard_number = false;
|
311
310
|
// If error, display the call stack (only once)
|
@@ -5183,7 +5182,16 @@ function VMI_push_var(x, args) {
|
|
5183
5182
|
}
|
5184
5183
|
if(Array.isArray(obj)) {
|
5185
5184
|
// Object is a vector
|
5186
|
-
|
5185
|
+
let v = t < obj.length ? obj[t] : VM.UNDEFINED;
|
5186
|
+
// NOTE: when the vector is the "active" parameter for sensitivity
|
5187
|
+
// analysis, the value is multiplied by 1 + delta %
|
5188
|
+
if(obj === MODEL.active_sensitivity_parameter) {
|
5189
|
+
// NOTE: do NOT scale exceptional values
|
5190
|
+
if(v > VM.MINUS_INFINITY && v < VM.PLUS_INFINITY) {
|
5191
|
+
v *= (1 + MODEL.sensitivity_delta * 0.01);
|
5192
|
+
}
|
5193
|
+
}
|
5194
|
+
x.push(v);
|
5187
5195
|
} else if(xv) {
|
5188
5196
|
// Variable references an earlier value computed for this expression `x`
|
5189
5197
|
x.push(t >= 0 && t < x.vector.length ? x.vector[t] : obj.dv);
|
@@ -5316,8 +5324,10 @@ function VMI_push_dataset_modifier(x, args) {
|
|
5316
5324
|
tot[1] + (tot[2] ? ':' + tot[2] : ''), ' value = ', VM.sig4Dig(v));
|
5317
5325
|
console.log(' --', x.text, ' for owner ', x.object.displayName, x.attribute);
|
5318
5326
|
}
|
5319
|
-
// NOTE:
|
5320
|
-
|
5327
|
+
// NOTE: if value is exceptional ("undefined", etc.), use default value
|
5328
|
+
if(v >= VM.PLUS_INFINITY) v = ds.defaultValue;
|
5329
|
+
// Finally, push the value onto the expression stack
|
5330
|
+
x.push(v);
|
5321
5331
|
}
|
5322
5332
|
|
5323
5333
|
|