linny-r 1.2.0 → 1.3.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 +6 -6
- package/console.js +2 -2
- package/package.json +2 -2
- package/static/images/paste.png +0 -0
- package/static/index.html +55 -6
- package/static/linny-r.css +100 -22
- package/static/scripts/linny-r-ctrl.js +26 -4
- package/static/scripts/linny-r-gui.js +940 -119
- package/static/scripts/linny-r-model.js +203 -37
- package/static/scripts/linny-r-utils.js +49 -11
- package/static/scripts/linny-r-vm.js +29 -18
@@ -12,7 +12,7 @@ executed by the VM, construct the Simplex tableau that can be sent to the
|
|
12
12
|
MILP solver.
|
13
13
|
*/
|
14
14
|
/*
|
15
|
-
Copyright (c) 2017-
|
15
|
+
Copyright (c) 2017-2023 Delft University of Technology
|
16
16
|
|
17
17
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
18
18
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -834,7 +834,7 @@ class ExpressionParser {
|
|
834
834
|
return [stat, list, anchor1, offset1, anchor2, offset2];
|
835
835
|
}
|
836
836
|
this.error = `No entities that match pattern "${patstr}"` +
|
837
|
-
(attr ? ' and have attribute ' + attr : '');
|
837
|
+
(attr ? ' and have attribute ' + attr : ' when no attribute is specified');
|
838
838
|
return false;
|
839
839
|
}
|
840
840
|
|
@@ -1428,6 +1428,8 @@ class VirtualMachine {
|
|
1428
1428
|
this.lines = '';
|
1429
1429
|
// String specifying a numeric issue (empty if none)
|
1430
1430
|
this.numeric_issue = '';
|
1431
|
+
// Warnings are stored in a list to permit browsing through them
|
1432
|
+
this.issue_list = [];
|
1431
1433
|
// The call stack tracks evaluation of "nested" expression variables
|
1432
1434
|
this.call_stack = [];
|
1433
1435
|
this.block_count = 0;
|
@@ -1553,6 +1555,9 @@ class VirtualMachine {
|
|
1553
1555
|
this.ERROR, this.CYCLIC, this.DIV_ZERO, this.BAD_CALC, this.ARRAY_INDEX,
|
1554
1556
|
this.BAD_REF, this.UNDERFLOW, this.OVERFLOW, this.INVALID, this.PARAMS,
|
1555
1557
|
this.UNKNOWN_ERROR, this.UNDEFINED, this.NOT_COMPUTED, this.COMPUTING];
|
1558
|
+
|
1559
|
+
// Prefix for warning messages that are logged in the monitor
|
1560
|
+
this.WARNING = '-- Warning: ';
|
1556
1561
|
|
1557
1562
|
// Solver constants indicating constraint type
|
1558
1563
|
// NOTE: these correspond to the codes used by LP_solve; when generating
|
@@ -1695,6 +1700,10 @@ class VirtualMachine {
|
|
1695
1700
|
// Initialize error counters (error count will be reset to 0 for each block)
|
1696
1701
|
this.error_count = 0;
|
1697
1702
|
this.block_issues = 0;
|
1703
|
+
// Clear issue list with warnings and hide issue panel
|
1704
|
+
this.issue_list.length = 0;
|
1705
|
+
this.issue_index = -1;
|
1706
|
+
UI.updateIssuePanel();
|
1698
1707
|
// NOTE: special tracking of potential solver license errors
|
1699
1708
|
this.license_expired = 0;
|
1700
1709
|
// Reset solver result arrays
|
@@ -2085,6 +2094,10 @@ class VirtualMachine {
|
|
2085
2094
|
this.messages[block - 1] = '';
|
2086
2095
|
}
|
2087
2096
|
this.messages[block - 1] += msg + '\n';
|
2097
|
+
if(msg.startsWith(this.WARNING)) {
|
2098
|
+
this.error_count++;
|
2099
|
+
this.issue_list.push(msg);
|
2100
|
+
}
|
2088
2101
|
// Show message on console or in Monitor dialog
|
2089
2102
|
MONITOR.logMessage(block, msg);
|
2090
2103
|
}
|
@@ -2125,7 +2138,7 @@ class VirtualMachine {
|
|
2125
2138
|
MONITOR.updateContent('msg');
|
2126
2139
|
}
|
2127
2140
|
}
|
2128
|
-
|
2141
|
+
|
2129
2142
|
startTimer() {
|
2130
2143
|
// Record time of this reset
|
2131
2144
|
this.reset_time = new Date().getTime();
|
@@ -3627,14 +3640,12 @@ class VirtualMachine {
|
|
3627
3640
|
a.cash_flow[b] = a.cash_in[b] - a.cash_out[b];
|
3628
3641
|
// Count occurrences of a negative cash flow (threshold -0.5 cent)
|
3629
3642
|
if(a.cash_in[b] < -0.005) {
|
3630
|
-
this.logMessage(block,
|
3643
|
+
this.logMessage(block, `${this.WARNING}(t=${b}${round}) ` +
|
3631
3644
|
a.displayName + ' cash IN = ' + a.cash_in[b].toPrecision(2));
|
3632
|
-
this.error_count++;
|
3633
3645
|
}
|
3634
3646
|
if(a.cash_out[b] < -0.005) {
|
3635
|
-
this.logMessage(block,
|
3647
|
+
this.logMessage(block, `${this.WARNING}(t=${b}${round}) ` +
|
3636
3648
|
a.displayName + ' cash IN = ' + a.cash_out[b].toPrecision(2));
|
3637
|
-
this.error_count++;
|
3638
3649
|
}
|
3639
3650
|
// Advance column offset in tableau by the # cols per time step
|
3640
3651
|
j += this.cols;
|
@@ -3754,7 +3765,7 @@ class VirtualMachine {
|
|
3754
3765
|
v[1].constraint.slack_info[b] = v[0];
|
3755
3766
|
}
|
3756
3767
|
if(absl > VM.SIG_DIF_FROM_ZERO) {
|
3757
|
-
this.logMessage(block,
|
3768
|
+
this.logMessage(block, `${this.WARNING}(t=${b}${round}) ` +
|
3758
3769
|
`${v[1].displayName} ${v[0]} slack = ${this.sig4Dig(slack)}`);
|
3759
3770
|
if(v[1] instanceof Product) {
|
3760
3771
|
const ppc = v[1].productPositionClusters;
|
@@ -3762,7 +3773,6 @@ class VirtualMachine {
|
|
3762
3773
|
ppc[ci].usesSlack(b, v[1], v[0]);
|
3763
3774
|
}
|
3764
3775
|
}
|
3765
|
-
this.error_count++;
|
3766
3776
|
} else if(CONFIGURATION.slight_slack_notices) {
|
3767
3777
|
this.logMessage(block, '-- Notice: (t=' + b + round + ') ' +
|
3768
3778
|
v[1].displayName + ' ' + v[0] + ' slack = ' +
|
@@ -3932,9 +3942,8 @@ class VirtualMachine {
|
|
3932
3942
|
b = bb;
|
3933
3943
|
for(let i = 0; i < this.chunk_length; i++) {
|
3934
3944
|
if(!MODEL.calculateCostPrices(b)) {
|
3935
|
-
this.logMessage(block,
|
3936
|
-
'
|
3937
|
-
this.error_count++;
|
3945
|
+
this.logMessage(block, `${this.WARNING}(t=${b}) ` +
|
3946
|
+
'Invalid cost prices due to negative flow(s)');
|
3938
3947
|
}
|
3939
3948
|
// move to the next time step of the block
|
3940
3949
|
b++;
|
@@ -4729,9 +4738,11 @@ Solver status = ${json.status}`);
|
|
4729
4738
|
// If experiment is active, signal the manager
|
4730
4739
|
if(MODEL.running_experiment) EXPERIMENT_MANAGER.processRun();
|
4731
4740
|
// Warn modeler if any issues occurred
|
4732
|
-
if(this.block_issues)
|
4733
|
-
|
4734
|
-
' --
|
4741
|
+
if(this.block_issues) {
|
4742
|
+
UI.warn('Issues occurred in ' + pluralS(this.block_issues, 'block') +
|
4743
|
+
' -- details can be viewed in the monitor and by using \u25C1 \u25B7');
|
4744
|
+
UI.updateIssuePanel();
|
4745
|
+
}
|
4735
4746
|
if(this.license_expired > 0) {
|
4736
4747
|
// Special message to draw attention to this critical error
|
4737
4748
|
UI.alert('SOLVER LICENSE EXPIRED: Please check!');
|
@@ -5189,15 +5200,15 @@ function relativeTimeStep(t, anchor, offset, dtm, x) {
|
|
5189
5200
|
}
|
5190
5201
|
if(anchor === 'c') {
|
5191
5202
|
// Relative to start of current optimization block
|
5192
|
-
return
|
5203
|
+
return Math.trunc(t / MODEL.block_length) * MODEL.block_length + offset;
|
5193
5204
|
}
|
5194
5205
|
if(anchor === 'p') {
|
5195
5206
|
// Relative to start of previous optimization block
|
5196
|
-
return
|
5207
|
+
return (Math.trunc(t / MODEL.block_length) - 1) * MODEL.block_length + offset;
|
5197
5208
|
}
|
5198
5209
|
if(anchor === 'n') {
|
5199
5210
|
// Relative to start of next optimization block
|
5200
|
-
return
|
5211
|
+
return (Math.trunc(t / MODEL.block_length) + 1) * MODEL.block_length + offset;
|
5201
5212
|
}
|
5202
5213
|
if(anchor === 'l') {
|
5203
5214
|
// Last: offset relative to the last index in the vector
|