linny-r 1.6.8 → 1.7.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/console.js +104 -220
- package/package.json +1 -1
- package/server.js +39 -133
- package/static/index.html +64 -5
- package/static/linny-r.css +41 -0
- package/static/scripts/linny-r-ctrl.js +31 -29
- 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-milp.js +363 -188
- package/static/scripts/linny-r-model.js +26 -12
- package/static/scripts/linny-r-vm.js +18 -4
@@ -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,
|
@@ -2328,7 +2328,13 @@ class VirtualMachine {
|
|
2328
2328
|
// Statistics that can be calculated for outcomes and experiment run results
|
2329
2329
|
this.outcome_statistics =
|
2330
2330
|
['LAST', 'MAX', 'MEAN', 'MIN', 'N', 'NZ', 'SD', 'SUM', 'VAR'];
|
2331
|
-
|
2331
|
+
this.solver_names = {
|
2332
|
+
gurobi: 'Gurobi',
|
2333
|
+
cplex: 'CPLEX',
|
2334
|
+
scip: 'SCIP',
|
2335
|
+
lp_solve: 'LP_solve'
|
2336
|
+
};
|
2337
|
+
}
|
2332
2338
|
|
2333
2339
|
reset() {
|
2334
2340
|
// Reset the virtual machine so that it can execute the model again.
|
@@ -2945,6 +2951,7 @@ class VirtualMachine {
|
|
2945
2951
|
return obj.la_peak_inc[c];
|
2946
2952
|
}
|
2947
2953
|
const prior_level = obj.actualLevel(t);
|
2954
|
+
//console.log('HERE obj prilev t', obj.displayName, prior_level, t, obj.level);
|
2948
2955
|
if(type === 'OO') return prior_level > 0 ? 1 : 0;
|
2949
2956
|
if(type === 'IZ') return prior_level === 0 ? 1 : 0;
|
2950
2957
|
// Start-up at time t entails that t is in the list of start-up
|
@@ -4305,7 +4312,7 @@ class VirtualMachine {
|
|
4305
4312
|
// Return floating point number `n`, or +INF or -INF if the absolute
|
4306
4313
|
// value of `n` is relatively (!) close to the VM infinity constants
|
4307
4314
|
// (since the solver may return imprecise values of such magnitude).
|
4308
|
-
|
4315
|
+
if(n > 0.5 * VM.PLUS_INFINITY && n < VM.BEYOND_PLUS_INFINITY) {
|
4309
4316
|
return VM.PLUS_INFINITY;
|
4310
4317
|
}
|
4311
4318
|
if(n < 0.5 * VM.MINUS_INFINITY && n > VM.BEYOND_MINUS_INFINITY) {
|
@@ -5719,7 +5726,7 @@ Solver status = ${json.status}`);
|
|
5719
5726
|
}
|
5720
5727
|
|
5721
5728
|
submitFile() {
|
5722
|
-
//
|
5729
|
+
// Prepare to POST the model file (LP or MPS) to the Linny-R server.
|
5723
5730
|
// NOTE: The tableau is no longer needed, so free up its memory.
|
5724
5731
|
this.resetTableau();
|
5725
5732
|
if(this.numeric_issue) {
|
@@ -5772,6 +5779,13 @@ Solver status = ${json.status}`);
|
|
5772
5779
|
solveModel() {
|
5773
5780
|
// Start the sequence of data loading, model translation, solving
|
5774
5781
|
// consecutive blocks, and finally calculating dependent variables.
|
5782
|
+
// NOTE: Do this only if the model defines a MILP problem, i.e.,
|
5783
|
+
// contains at least one process or product.
|
5784
|
+
if(!(Object.keys(MODEL.processes).length ||
|
5785
|
+
Object.keys(MODEL.products).length)) {
|
5786
|
+
UI.notify('Nothing to solve');
|
5787
|
+
return;
|
5788
|
+
}
|
5775
5789
|
const n = MODEL.loading_datasets.length;
|
5776
5790
|
if(n > 0) {
|
5777
5791
|
// Still within reasonable time? (3 seconds per dataset)
|
@@ -5780,7 +5794,7 @@ Solver status = ${json.status}`);
|
|
5780
5794
|
UI.setMessage(`Waiting for ${pluralS(n, 'dataset')} to load`);
|
5781
5795
|
// Decrease the remaining time to wait (half second units)
|
5782
5796
|
MODEL.max_time_to_load--;
|
5783
|
-
// Try again after half a second
|
5797
|
+
// Try again after half a second.
|
5784
5798
|
setTimeout(() => VM.solveModel(), 500);
|
5785
5799
|
return;
|
5786
5800
|
} else {
|