linny-r 1.6.8 → 1.7.1
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/console.js +250 -305
- package/package.json +1 -1
- package/server.js +40 -134
- package/static/index.html +64 -5
- package/static/linny-r.css +41 -0
- package/static/scripts/linny-r-ctrl.js +47 -42
- package/static/scripts/linny-r-gui-controller.js +153 -15
- package/static/scripts/linny-r-gui-monitor.js +21 -9
- package/static/scripts/linny-r-gui-paper.js +18 -18
- package/static/scripts/linny-r-gui-receiver.js +5 -5
- package/static/scripts/linny-r-milp.js +363 -188
- package/static/scripts/linny-r-model.js +43 -29
- package/static/scripts/linny-r-utils.js +20 -3
- package/static/scripts/linny-r-vm.js +162 -73
@@ -88,7 +88,6 @@ class LinnyRModel {
|
|
88
88
|
this.selected_round = 0;
|
89
89
|
|
90
90
|
// Model settings
|
91
|
-
this.timeout_period = 30; // max. solver time in seconds
|
92
91
|
this.block_length = 1;
|
93
92
|
this.start_period = 1; // defines starting point in datasets
|
94
93
|
this.end_period = 1;
|
@@ -99,6 +98,12 @@ class LinnyRModel {
|
|
99
98
|
this.report_results = false;
|
100
99
|
this.show_block_arrows = true;
|
101
100
|
this.last_zoom_factor = 1;
|
101
|
+
|
102
|
+
// Default solver settings
|
103
|
+
this.timeout_period = 30; // max. solver time in seconds
|
104
|
+
this.preferred_solver = ''; // empty string denotes "use default"
|
105
|
+
this.integer_tolerance = 5e-7; // integer feasibility tolerance
|
106
|
+
this.MIP_gap = 1e-4; // relative MIP gap
|
102
107
|
|
103
108
|
// Sensitivity-related properties
|
104
109
|
this.base_case_selectors = '';
|
@@ -140,17 +145,18 @@ class LinnyRModel {
|
|
140
145
|
/* METHODS THAT LOOKUP ENTITIES, OR INFER PROPERTIES */
|
141
146
|
|
142
147
|
get simulationTimeStep() {
|
143
|
-
//
|
144
|
-
// start of the simulation period
|
148
|
+
// Return actual model time step, rather than `t`, which is relative
|
149
|
+
// to the start of the simulation period.
|
145
150
|
return this.t + this.start_period - 1;
|
146
151
|
}
|
147
152
|
|
148
153
|
get timeStepDuration() {
|
149
|
-
//
|
154
|
+
// Return duration of 1 time step in hours.
|
150
155
|
return this.time_scale * VM.time_unit_values[this.time_unit];
|
151
156
|
}
|
152
157
|
|
153
158
|
get outcomes() {
|
159
|
+
// Return the list of outcome datasets.
|
154
160
|
const olist = [];
|
155
161
|
for(let k in this.datasets) if(this.datasets.hasOwnProperty(k)) {
|
156
162
|
if(this.datasets[k].outcome) olist.push(this.datasets[k]);
|
@@ -2631,17 +2637,17 @@ class LinnyRModel {
|
|
2631
2637
|
}
|
2632
2638
|
|
2633
2639
|
initFromXML(node) {
|
2634
|
-
// Initialize a model from the XML tree with `node` as root
|
2635
|
-
// NOTE: do NOT reset and initialize basic model properties when
|
2636
|
-
// a module into the current model
|
2637
|
-
// NOTE:
|
2640
|
+
// Initialize a model from the XML tree with `node` as root.
|
2641
|
+
// NOTE: do NOT reset and initialize basic model properties when
|
2642
|
+
// *including* a module into the current model.
|
2643
|
+
// NOTE: Obsolete XML nodes indicate: legacy Linny-R model.
|
2638
2644
|
const legacy_model = (nodeParameterValue(node, 'view-options') +
|
2639
2645
|
nodeParameterValue(node, 'autosave') +
|
2640
2646
|
nodeParameterValue(node, 'look-ahead') +
|
2641
2647
|
nodeParameterValue(node, 'save-series') +
|
2642
2648
|
nodeParameterValue(node, 'show-lp') +
|
2643
2649
|
nodeParameterValue(node, 'optional-slack')).length > 0;
|
2644
|
-
// Flag to set when legacy time series data are added
|
2650
|
+
// Flag to set when legacy time series data are added.
|
2645
2651
|
this.legacy_datasets = false;
|
2646
2652
|
if(!IO_CONTEXT) {
|
2647
2653
|
this.reset();
|
@@ -2668,7 +2674,12 @@ class LinnyRModel {
|
|
2668
2674
|
this.version = xmlDecoded(nodeContentByTag(node, 'version'));
|
2669
2675
|
this.timeout_period = Math.max(0,
|
2670
2676
|
safeStrToInt(nodeContentByTag(node, 'timeout-period')));
|
2671
|
-
|
2677
|
+
this.preferred_solver = xmlDecoded(
|
2678
|
+
nodeContentByTag(node, 'preferred-solver'));
|
2679
|
+
this.integer_tolerance = safeStrToFloat(
|
2680
|
+
nodeContentByTag(node, 'integer-tolerance'), 5e-7);
|
2681
|
+
this.MIP_gap = safeStrToFloat(nodeContentByTag(node, 'mip-gap'), 1e-4);
|
2682
|
+
// Legacy models have tag "optimization-period" instead of "block-length".
|
2672
2683
|
const bl_str = nodeContentByTag(node, 'block-length') ||
|
2673
2684
|
nodeContentByTag(node, 'optimization-period');
|
2674
2685
|
this.block_length = Math.max(1, safeStrToInt(node, bl_str));
|
@@ -2693,7 +2704,7 @@ class LinnyRModel {
|
|
2693
2704
|
if(!this.default_unit) this.default_unit = CONFIGURATION.default_scale_unit;
|
2694
2705
|
} // END IF *not* including a model
|
2695
2706
|
|
2696
|
-
// Declare some local variables that will be used a lot
|
2707
|
+
// Declare some local variables that will be used a lot.
|
2697
2708
|
let i,
|
2698
2709
|
c,
|
2699
2710
|
name,
|
@@ -3014,7 +3025,10 @@ class LinnyRModel {
|
|
3014
3025
|
'</default-scale-unit><currency-unit>', xmlEncoded(this.currency_unit),
|
3015
3026
|
'</currency-unit><grid-pixels>', this.grid_pixels,
|
3016
3027
|
'</grid-pixels><timeout-period>', this.timeout_period,
|
3017
|
-
'</timeout-period><
|
3028
|
+
'</timeout-period><preferred-solver>', xmlEncoded(this.preferred_solver),
|
3029
|
+
'</preferred-solver><integer-tolerance>', this.integer_tolerance,
|
3030
|
+
'</integer-tolerance><mip-gap>', this.MIP_gap,
|
3031
|
+
'</mip-gap><block-length>', this.block_length,
|
3018
3032
|
'</block-length><start-period>', this.start_period,
|
3019
3033
|
'</start-period><end-period>', this.end_period,
|
3020
3034
|
'</end-period><look-ahead-period>', this.look_ahead,
|
@@ -7110,24 +7124,24 @@ class Cluster extends NodeBox {
|
|
7110
7124
|
class Node extends NodeBox {
|
7111
7125
|
constructor(cluster, name, actor) {
|
7112
7126
|
super(cluster, name, actor);
|
7113
|
-
// Nodes are assigned a unique code as "shorthand notation"
|
7114
|
-
// NOTE:
|
7127
|
+
// Nodes are assigned a unique code as "shorthand notation".
|
7128
|
+
// NOTE: Decimal numbers for processes, Excel-style letter codes for
|
7115
7129
|
// products, i.e., A, ..., Z, AA, AB, etc.
|
7116
7130
|
this.code = null;
|
7117
|
-
// By default, nodes are NOT data products (only products can become data
|
7131
|
+
// By default, nodes are NOT data products (only products can become data).
|
7118
7132
|
this.is_data = false;
|
7119
|
-
// By default, node levels are continuous, but may be set to integer
|
7133
|
+
// By default, node levels are continuous, but may be set to integer.
|
7120
7134
|
this.integer_level = false;
|
7121
|
-
// Processes and products both have input attributes LB, UB and IL,
|
7122
|
-
// result attributes L and CP
|
7135
|
+
// Processes and products both have input attributes LB, UB and IL,
|
7136
|
+
// and result attributes L and CP.
|
7123
7137
|
this.lower_bound = new Expression(this, 'LB', '');
|
7124
7138
|
this.upper_bound = new Expression(this, 'UB', '');
|
7125
7139
|
this.initial_level = new Expression(this, 'IL', '0');
|
7126
7140
|
this.cost_price = [];
|
7127
|
-
// NOTE:
|
7128
|
-
// the stock level
|
7141
|
+
// NOTE: For processes, level denotes the production level, for products
|
7142
|
+
// the stock level.
|
7129
7143
|
this.level = [];
|
7130
|
-
// `inputs` is array of incoming links, `outputs` is array of outgoing links
|
7144
|
+
// `inputs` is array of incoming links, `outputs` is array of outgoing links.
|
7131
7145
|
this.inputs = [];
|
7132
7146
|
this.outputs = [];
|
7133
7147
|
this.predecessors = [];
|
@@ -7148,13 +7162,13 @@ class Node extends NodeBox {
|
|
7148
7162
|
}
|
7149
7163
|
|
7150
7164
|
get hasBounds() {
|
7151
|
-
//
|
7165
|
+
// Return TRUE if lower or upper bound is defined for this node.
|
7152
7166
|
return this.upper_bound.defined || this.lower_bound.defined;
|
7153
7167
|
}
|
7154
7168
|
|
7155
7169
|
setConstraintOffsets() {
|
7156
|
-
//
|
7157
|
-
// node
|
7170
|
+
// Set the offset properties of the constraints that relate to this
|
7171
|
+
// node. These properties are used when drawing these constraints.
|
7158
7172
|
const tbc = {top: [], bottom: [], thumb: []};
|
7159
7173
|
for(let k in MODEL.constraints) if(MODEL.constraints.hasOwnProperty(k)) {
|
7160
7174
|
const
|
@@ -7412,14 +7426,14 @@ class Node extends NodeBox {
|
|
7412
7426
|
}
|
7413
7427
|
|
7414
7428
|
canConstrain(node) {
|
7415
|
-
//
|
7416
|
-
// NOTE: A node cannot constrain itself, and BOTH nodes must have upper bounds
|
7429
|
+
// Return TRUE if this node can constrain `node`.
|
7430
|
+
// NOTE: A node cannot constrain itself, and BOTH nodes must have upper bounds.
|
7417
7431
|
return this !== node && this.upper_bound.defined && node.upper_bound.defined;
|
7418
7432
|
}
|
7419
7433
|
|
7420
7434
|
get costAddingConstraints() {
|
7421
|
-
//
|
7422
|
-
// transfer cost to this node
|
7435
|
+
// Return a (possibly empty) list of composite constraints that can
|
7436
|
+
// transfer cost to this node.
|
7423
7437
|
let cac = [];
|
7424
7438
|
for(let k in MODEL.constraints) if(MODEL.constraints.hasOwnProperty(k)) {
|
7425
7439
|
const c = MODEL.constraints[k];
|
@@ -7434,7 +7448,7 @@ class Node extends NodeBox {
|
|
7434
7448
|
|
7435
7449
|
convertLegacyBoundData(lb_data, ub_data) {
|
7436
7450
|
// Convert time series data for LB and UB in legacy models to datasets,
|
7437
|
-
// and replace attribute expressions by references to these datasets
|
7451
|
+
// and replace attribute expressions by references to these datasets.
|
7438
7452
|
if(!lb_data && !ub_data) return;
|
7439
7453
|
const same = lb_data === ub_data;
|
7440
7454
|
if(lb_data) {
|
@@ -1076,6 +1076,7 @@ if(NODE) module.exports = {
|
|
1076
1076
|
msecToTime: msecToTime,
|
1077
1077
|
compactClockTime: compactClockTime,
|
1078
1078
|
uniformDecimals: uniformDecimals,
|
1079
|
+
capitalized: capitalized,
|
1079
1080
|
ellipsedText: ellipsedText,
|
1080
1081
|
earlierVersion: earlierVersion,
|
1081
1082
|
differences: differences,
|
@@ -1083,12 +1084,23 @@ if(NODE) module.exports = {
|
|
1083
1084
|
ciCompare: ciCompare,
|
1084
1085
|
endsWithDigits: endsWithDigits,
|
1085
1086
|
indexOfMatchingBracket: indexOfMatchingBracket,
|
1087
|
+
monoSpaced: monoSpaced,
|
1088
|
+
monoSpacedVariables: monoSpacedVariables,
|
1086
1089
|
patternList: patternList,
|
1087
1090
|
patternMatch: patternMatch,
|
1088
|
-
|
1089
|
-
stringToFloatArray: stringToFloatArray,
|
1091
|
+
matchingWildcardNumber: matchingWildcardNumber,
|
1090
1092
|
escapeRegex: escapeRegex,
|
1093
|
+
wildcardMatchRegex: wildcardMatchRegex,
|
1094
|
+
wildcardFormat: wildcardFormat,
|
1095
|
+
matchingNumber: matchingNumber,
|
1096
|
+
matchingNumberInList: matchingNumberInList,
|
1097
|
+
compareWithTailNumbers: compareWithTailNumbers,
|
1098
|
+
compareSelectors: compareSelectors,
|
1099
|
+
compareCombinations: compareCombinations,
|
1091
1100
|
addDistinct: addDistinct,
|
1101
|
+
mergeDistinct: mergeDistinct,
|
1102
|
+
iteratorSet: iteratorSet,
|
1103
|
+
integerSet: integerSet,
|
1092
1104
|
setString: setString,
|
1093
1105
|
tupelString: tupelString,
|
1094
1106
|
tupelSetString: tupelSetString,
|
@@ -1097,6 +1109,7 @@ if(NODE) module.exports = {
|
|
1097
1109
|
complement: complement,
|
1098
1110
|
xmlEncoded: xmlEncoded,
|
1099
1111
|
xmlDecoded: xmlDecoded,
|
1112
|
+
customizeXML: customizeXML,
|
1100
1113
|
cleanXML: cleanXML,
|
1101
1114
|
parseXML: parseXML,
|
1102
1115
|
childNodeByTag: childNodeByTag,
|
@@ -1107,12 +1120,16 @@ if(NODE) module.exports = {
|
|
1107
1120
|
parseLetterCode: parseLetterCode,
|
1108
1121
|
randomID: randomID,
|
1109
1122
|
escapedSingleQuotes: escapedSingleQuotes,
|
1123
|
+
safeDoubleQuotes: safeDoubleQuotes,
|
1110
1124
|
nameToLines: nameToLines,
|
1125
|
+
hexToFloat: hexToFloat,
|
1126
|
+
stringToFloatArray: stringToFloatArray,
|
1111
1127
|
hexToBytes: hexToBytes,
|
1128
|
+
bytesToHex: bytesToHex,
|
1112
1129
|
arrayBufferToBase64: arrayBufferToBase64,
|
1113
1130
|
base64ToArrayBuffer: base64ToArrayBuffer,
|
1114
1131
|
encryptionKey: encryptionKey,
|
1115
1132
|
encryptMessage: encryptMessage,
|
1116
1133
|
decryptMessage: decryptMessage,
|
1117
|
-
tryToDecrypt: tryToDecrypt
|
1134
|
+
tryToDecrypt: tryToDecrypt
|
1118
1135
|
}
|