linny-r 1.8.2 → 1.9.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/package.json +1 -1
- package/static/images/sel-order.png +0 -0
- package/static/index.html +31 -2
- package/static/linny-r.css +25 -0
- package/static/scripts/linny-r-config.js +1 -1
- package/static/scripts/linny-r-gui-controller.js +8 -1
- package/static/scripts/linny-r-gui-equation-manager.js +20 -2
- package/static/scripts/linny-r-gui-experiment-manager.js +25 -1
- package/static/scripts/linny-r-gui-expression-editor.js +2 -1
- package/static/scripts/linny-r-gui-file-manager.js +6 -1
- package/static/scripts/linny-r-gui-finder.js +74 -43
- package/static/scripts/linny-r-gui-model-autosaver.js +4 -1
- package/static/scripts/linny-r-gui-monitor.js +1 -0
- package/static/scripts/linny-r-gui-repository-browser.js +6 -5
- package/static/scripts/linny-r-milp.js +8 -6
- package/static/scripts/linny-r-model.js +45 -28
- package/static/scripts/linny-r-utils.js +35 -9
- package/static/scripts/linny-r-vm.js +108 -60
@@ -317,6 +317,7 @@ class Expression {
|
|
317
317
|
if((typeof number !== 'number' ||
|
318
318
|
(this.isStatic && !this.isWildcardExpression)) &&
|
319
319
|
!this.isMethod) return this.vector;
|
320
|
+
//console.log('HERE choosing wcnr', number, this);
|
320
321
|
// Method expressions are not "numbered" but differentiate by the
|
321
322
|
// entity to which they are applied. Their "vector number" is then
|
322
323
|
// inferred by looking up this entity in a method object list.
|
@@ -331,7 +332,9 @@ class Expression {
|
|
331
332
|
}
|
332
333
|
// Use the vector for the wildcard number (create it if necessary).
|
333
334
|
if(!this.wildcard_vectors.hasOwnProperty(number)) {
|
335
|
+
//console.log('HERE adding wc vector', number, this);
|
334
336
|
this.wildcard_vectors[number] = [];
|
337
|
+
//console.log('HERE adding wc vector', number, this.wildcard_vectors);
|
335
338
|
if(this.isStatic) {
|
336
339
|
this.wildcard_vectors[number][0] = VM.NOT_COMPUTED;
|
337
340
|
} else {
|
@@ -427,20 +430,25 @@ class Expression {
|
|
427
430
|
}
|
428
431
|
|
429
432
|
result(t, number=false) {
|
430
|
-
//
|
433
|
+
// Compute (only if needed) and then returns result for time step t.
|
431
434
|
// The `number` is passed only by the VMI_push_dataset_modifier
|
432
|
-
// instruction so as to force recomputation of the expression
|
433
|
-
//
|
434
|
-
// "initial value" (these follow from the variables used in the expression)
|
435
|
-
// Select the vector to use
|
435
|
+
// instruction so as to force recomputation of the expression.
|
436
|
+
// Select the vector to use.
|
436
437
|
const v = this.chooseVector(number);
|
437
438
|
if(!Array.isArray(v)) {
|
438
439
|
console.log('ANOMALY: No vector for result(t)');
|
439
440
|
return VM.UNDEFINED;
|
440
441
|
}
|
442
|
+
// NOTE: For t < 1 return the value for t = 1, since expressions have
|
443
|
+
// no "initial value" (these follow from the variables used in the
|
444
|
+
// expression).
|
441
445
|
if(t < 0 || this.isStatic) t = 0;
|
442
446
|
if(t >= v.length) return VM.UNDEFINED;
|
443
|
-
|
447
|
+
// NOTE: When VM is setting up a tableau, values computed for the
|
448
|
+
// look-ahead period must be recomputed.
|
449
|
+
if(v[t] === VM.NOT_COMPUTED || v[t] === VM.COMPUTING ||
|
450
|
+
(!this.isStatic && VM.inLookAhead(t))) {
|
451
|
+
v[t] = VM.NOT_COMPUTED;
|
444
452
|
this.compute(t, number);
|
445
453
|
}
|
446
454
|
// NOTE: when this expression is the "active" parameter for sensitivity
|
@@ -2136,8 +2144,8 @@ class VirtualMachine {
|
|
2136
2144
|
this.SOLVER_MINUS_INFINITY = -1e+30;
|
2137
2145
|
// As of version 1.8.0, Linny-R imposes no +INF bounds on processes
|
2138
2146
|
// unless diagnosing an unbounded problem. For such diagnosis, the
|
2139
|
-
// (relatively) low value 9.
|
2140
|
-
this.DIAGNOSIS_UPPER_BOUND = 9.
|
2147
|
+
// (relatively) low value 9.999999999e+9 is used.
|
2148
|
+
this.DIAGNOSIS_UPPER_BOUND = 9.999999999e+9;
|
2141
2149
|
// NOTE: Below the "near zero" limit, a number is considered zero
|
2142
2150
|
// (this is to timely detect division-by-zero errors).
|
2143
2151
|
this.NEAR_ZERO = 1e-10;
|
@@ -2149,7 +2157,8 @@ class VirtualMachine {
|
|
2149
2157
|
// their target without displaying them in red or blue to signal
|
2150
2158
|
// shortage or surplus.
|
2151
2159
|
this.SIG_DIF_LIMIT = 0.001;
|
2152
|
-
|
2160
|
+
// Numbers near zero are displayed as +0 or -0.
|
2161
|
+
this.SIG_DIF_FROM_ZERO = 5e-5;
|
2153
2162
|
// ON/OFF threshold is used to differentiate between level = 0 and
|
2154
2163
|
// still "ON" (will be displayed as +0).
|
2155
2164
|
this.ON_OFF_THRESHOLD = 1.5e-4;
|
@@ -2194,6 +2203,7 @@ class VirtualMachine {
|
|
2194
2203
|
this.LM_NEEDING_ON_OFF = [5, 6, 7, 8, 9, 10];
|
2195
2204
|
this.LM_SYMBOLS = ['', '\u21C9', '\u0394', '\u03A3', '\u03BC', '\u25B2',
|
2196
2205
|
'+', '0', '\u2934', '\u2732', '\u25BC', '\u2A39'];
|
2206
|
+
this.LM_LETTERS = ' TDSMU+0RFDP';
|
2197
2207
|
|
2198
2208
|
// VM max. expression stack size.
|
2199
2209
|
this.MAX_STACK = 200;
|
@@ -2472,8 +2482,19 @@ class VirtualMachine {
|
|
2472
2482
|
this.t = 0;
|
2473
2483
|
// Prepare for halt.
|
2474
2484
|
this.halted = false;
|
2485
|
+
// Flag to indicate that VM is executing its tableau construction code.
|
2486
|
+
// This affects how chunk time (ct) is computed, and whether expression
|
2487
|
+
// results must be recomputed (see inLookAhead below).
|
2488
|
+
this.executing_tableau_code = false;
|
2475
2489
|
UI.readyToSolve();
|
2476
2490
|
}
|
2491
|
+
|
2492
|
+
inLookAhead(t) {
|
2493
|
+
// Return TRUE if VM is executing its tableau construction code AND
|
2494
|
+
// time step `t` falls in the look-ahead period of the previous block.
|
2495
|
+
return this.executing_tableau_code &&
|
2496
|
+
t - (this.block_count - 1) * MODEL.block_length <= MODEL.look_ahead;
|
2497
|
+
}
|
2477
2498
|
|
2478
2499
|
errorMessage(n) {
|
2479
2500
|
// VM errors are very big NEGATIVE numbers, so start comparing `n`
|
@@ -2537,7 +2558,7 @@ class VirtualMachine {
|
|
2537
2558
|
if(sv[0]) return sv[1];
|
2538
2559
|
const a = Math.abs(n);
|
2539
2560
|
// Signal small differences from true 0 by leading + or - sign.
|
2540
|
-
if(n !== 0 && a
|
2561
|
+
if(n !== 0 && a <= this.ON_OFF_THRESHOLD) return n > 0 ? '+0' : '-0';
|
2541
2562
|
if(a >= 999999.5) return n.toPrecision(2);
|
2542
2563
|
if(Math.abs(a-Math.round(a)) < 0.05) return Math.round(n);
|
2543
2564
|
if(a < 1) return Math.round(n*100) / 100;
|
@@ -2556,7 +2577,7 @@ class VirtualMachine {
|
|
2556
2577
|
if(sv[0]) return sv[1];
|
2557
2578
|
const a = Math.abs(n);
|
2558
2579
|
// Signal small differences from true 0 by a leading + or - sign.
|
2559
|
-
if(n !== 0 && a
|
2580
|
+
if(n !== 0 && a <= this.ON_OFF_THRESHOLD) return n > 0 ? '+0' : '-0';
|
2560
2581
|
if(a >= 9999995) return n.toPrecision(4);
|
2561
2582
|
if(Math.abs(a-Math.round(a)) < 0.0005) return Math.round(n);
|
2562
2583
|
if(a < 1) return Math.round(n*10000) / 10000;
|
@@ -2866,7 +2887,7 @@ class VirtualMachine {
|
|
2866
2887
|
const
|
2867
2888
|
bm = r.block_messages[i],
|
2868
2889
|
err = (bm.messages.indexOf('Solver status = 0') < 0 ||
|
2869
|
-
bm.messages.indexOf(
|
2890
|
+
bm.messages.indexOf(this.WARNING) >= 0);
|
2870
2891
|
this.solver_times.push(bm.solver_time);
|
2871
2892
|
this.messages.push(bm.messages);
|
2872
2893
|
this.variables.push(this.no_variables);
|
@@ -2922,19 +2943,20 @@ class VirtualMachine {
|
|
2922
2943
|
for(let i = 2; i <= n; i++) {
|
2923
2944
|
this.variables.push(['W' + i, obj]);
|
2924
2945
|
}
|
2925
|
-
// NOTE:
|
2926
|
-
//
|
2927
|
-
|
2928
|
-
|
2929
|
-
|
2930
|
-
|
2931
|
-
|
2932
|
-
|
2933
|
-
|
2934
|
-
|
2935
|
-
|
2936
|
-
|
2937
|
-
|
2946
|
+
// NOTE: SOS constraints are not needed when a bound line defines
|
2947
|
+
// a convex feasible area.
|
2948
|
+
if(!obj.needsNoSOS) {
|
2949
|
+
this.sos_var_indices.push([index, n]);
|
2950
|
+
// NOTE: Some solvers do not support SOS. To ensure that only 2
|
2951
|
+
// adjacent w[i]-variables are non-zero (they range from 0 to 1),
|
2952
|
+
// as many binary variables b[i] must be defined, and additional
|
2953
|
+
// constraints must be added (see VMI_add_bound_line_constraint).
|
2954
|
+
if(this.noSupportForSOS) {
|
2955
|
+
for(let i = 1; i <= n; i++) {
|
2956
|
+
const bi = this.variables.push(['b' + i, obj]);
|
2957
|
+
this.bin_var_indices[bi] = true;
|
2958
|
+
}
|
2959
|
+
}
|
2938
2960
|
}
|
2939
2961
|
}
|
2940
2962
|
return index;
|
@@ -4044,7 +4066,7 @@ class VirtualMachine {
|
|
4044
4066
|
these variables can take on higher values. The modeler must ensure
|
4045
4067
|
that there is a cost associated with the actual flow, not a revenue.
|
4046
4068
|
*/
|
4047
|
-
// NOTE:
|
4069
|
+
// NOTE: As of 20 June 2021, binary attributes of products are also computed.
|
4048
4070
|
const pp_nodes = [];
|
4049
4071
|
for(i = 0; i < process_keys.length; i++) {
|
4050
4072
|
k = process_keys[i];
|
@@ -4093,8 +4115,8 @@ class VirtualMachine {
|
|
4093
4115
|
[VMI_add_const_to_coefficient, [p.level_var_index, 1]]
|
4094
4116
|
);
|
4095
4117
|
if(ubx.isStatic) {
|
4096
|
-
// If UB is very high (typically: undefined, so +INF), try to
|
4097
|
-
// a lower value for UB to use for the ON/OFF binary
|
4118
|
+
// If UB is very high (typically: undefined, so +INF), try to
|
4119
|
+
// infer a lower value for UB to use for the ON/OFF binary.
|
4098
4120
|
let ub = ubx.result(0),
|
4099
4121
|
hub = ub;
|
4100
4122
|
if(ub > VM.MEGA_UPPER_BOUND) {
|
@@ -4642,7 +4664,7 @@ class VirtualMachine {
|
|
4642
4664
|
if(v[1] instanceof BoundLine) {
|
4643
4665
|
v[1].constraint.slack_info[b] = v[0];
|
4644
4666
|
}
|
4645
|
-
if(b <= this.nr_of_time_steps && absl > VM.
|
4667
|
+
if(b <= this.nr_of_time_steps && absl > VM.ON_OFF_THRESHOLD) {
|
4646
4668
|
this.logMessage(block, `${this.WARNING}(t=${b}${round}) ` +
|
4647
4669
|
`${v[1].displayName} ${v[0]} slack = ${this.sig4Dig(slack)}`);
|
4648
4670
|
if(v[1] instanceof Product) {
|
@@ -4651,10 +4673,10 @@ class VirtualMachine {
|
|
4651
4673
|
ppc[ci].usesSlack(b, v[1], v[0]);
|
4652
4674
|
}
|
4653
4675
|
}
|
4654
|
-
} else if(
|
4655
|
-
this.logMessage(block, '
|
4676
|
+
} else if(MODEL.show_notices) {
|
4677
|
+
this.logMessage(block, '---- Notice: (t=' + b + round + ') ' +
|
4656
4678
|
v[1].displayName + ' ' + v[0] + ' slack = ' +
|
4657
|
-
slack.toPrecision(
|
4679
|
+
slack.toPrecision(1));
|
4658
4680
|
}
|
4659
4681
|
}
|
4660
4682
|
}
|
@@ -5217,7 +5239,7 @@ class VirtualMachine {
|
|
5217
5239
|
}
|
5218
5240
|
|
5219
5241
|
addTableauSegment(start, abl) {
|
5220
|
-
if(
|
5242
|
+
if(this.halted) {
|
5221
5243
|
this.hideSetUpOrWriteProgress();
|
5222
5244
|
this.stopSolving();
|
5223
5245
|
return;
|
@@ -5227,6 +5249,7 @@ class VirtualMachine {
|
|
5227
5249
|
var l;
|
5228
5250
|
const next_start = (start + this.tsl * 1.2 < abl ? start + this.tsl : abl);
|
5229
5251
|
for(let i = start; i < next_start; i++) {
|
5252
|
+
this.executing_tableau_code = true;
|
5230
5253
|
this.logTrace('EXECUTE for t=' + this.t);
|
5231
5254
|
l = this.code.length;
|
5232
5255
|
for(let j = 0; j < l; j++) {
|
@@ -5238,6 +5261,7 @@ class VirtualMachine {
|
|
5238
5261
|
this.logTrace([(' ' + j).slice(-5), ': coeff = ',
|
5239
5262
|
JSON.stringify(this.coefficients), '; rhs = ', this.rhs].join(''));
|
5240
5263
|
}
|
5264
|
+
this.executing_tableau_code = false;
|
5241
5265
|
this.logTrace('STOP executing block code');
|
5242
5266
|
// Add constraints for paced process variables.
|
5243
5267
|
// NOTE: This is effectuated by *executing* VM instructions.
|
@@ -5410,7 +5434,7 @@ class VirtualMachine {
|
|
5410
5434
|
this.numeric_issue = '';
|
5411
5435
|
// First add the objective (always MAXimize).
|
5412
5436
|
if(cplex) {
|
5413
|
-
this.lines =
|
5437
|
+
this.lines = `\\${this.solver_id}\nMaximize\n`;
|
5414
5438
|
} else {
|
5415
5439
|
this.lines = '/* Objective function */\nmax:\n';
|
5416
5440
|
}
|
@@ -5461,6 +5485,12 @@ class VirtualMachine {
|
|
5461
5485
|
}
|
5462
5486
|
}
|
5463
5487
|
c = this.right_hand_side[r];
|
5488
|
+
// NOTE: When previous block was infeasible or unbounded (no solution),
|
5489
|
+
// expressions for RHS may not evaluate as a number.
|
5490
|
+
if(Number.isNaN(c)) {
|
5491
|
+
this.setNumericIssue(c, r, 'constraint RHS');
|
5492
|
+
c = 0;
|
5493
|
+
}
|
5464
5494
|
this.lines += line + ' ' +
|
5465
5495
|
this.constraint_symbols[this.constraint_types[r]] + ' ' + c + EOL;
|
5466
5496
|
line = '';
|
@@ -5507,8 +5537,14 @@ class VirtualMachine {
|
|
5507
5537
|
}
|
5508
5538
|
} else {
|
5509
5539
|
// Bounds can be specified on a single line: lb <= X001 <= ub.
|
5510
|
-
|
5511
|
-
|
5540
|
+
// NOTE: LP_solve has Infinity value 1e+25. Use this literal
|
5541
|
+
// because VM.PLUS_INFINITY may be set to *diagnostic* value.
|
5542
|
+
if(lb !== null && lb !== 0 && lb > -1e+25) {
|
5543
|
+
line = lb + ' <= ' + line;
|
5544
|
+
}
|
5545
|
+
if(ub !== null && ub < 1e+25) line += ' <= ' + ub;
|
5546
|
+
// NOTE: Do not add line if both bounds are infinite.
|
5547
|
+
if(line.indexOf('<=') < 0) line = '';
|
5512
5548
|
}
|
5513
5549
|
}
|
5514
5550
|
if(line) this.lines += line + EOL;
|
@@ -5568,19 +5604,17 @@ class VirtualMachine {
|
|
5568
5604
|
// NOTE: Add SOS section only if the solver supports SOS.
|
5569
5605
|
if(this.sos_var_indices.length > 0 && !this.noSupportForSOS) {
|
5570
5606
|
this.lines += 'SOS\n';
|
5571
|
-
let sos = 0;
|
5572
5607
|
const v_set = [];
|
5573
5608
|
for(let j = 0; j < abl; j++) {
|
5574
5609
|
for(let i = 0; i < this.sos_var_indices.length; i++) {
|
5610
|
+
const svi = this.sos_var_indices[i];
|
5575
5611
|
v_set.length = 0;
|
5576
|
-
let vi =
|
5577
|
-
|
5578
|
-
for(let j = 1; j <= n; j++) {
|
5612
|
+
let vi = svi[0] + j * this.cols;
|
5613
|
+
for(let j = 1; j <= svi[1]; j++) {
|
5579
5614
|
v_set.push(`${vbl(vi)}:${j}`);
|
5580
5615
|
vi++;
|
5581
5616
|
}
|
5582
|
-
this.lines += ` s${
|
5583
|
-
sos++;
|
5617
|
+
this.lines += ` s${i}: S2:: ${v_set.join(' ')}\n`;
|
5584
5618
|
}
|
5585
5619
|
}
|
5586
5620
|
}
|
@@ -5605,18 +5639,16 @@ class VirtualMachine {
|
|
5605
5639
|
// LP_solve supports SOS, so add the SOS section if needed.
|
5606
5640
|
if(this.sos_var_indices.length > 0) {
|
5607
5641
|
this.lines += 'sos\n';
|
5608
|
-
let sos = 1;
|
5609
5642
|
for(let j = 0; j < abl; j++) {
|
5610
5643
|
for(let i = 0; i < this.sos_var_indices.length; i++) {
|
5644
|
+
const svi = this.sos_var_indices[i];
|
5611
5645
|
v_set.length = 0;
|
5612
|
-
let vi =
|
5613
|
-
|
5614
|
-
for(let j = 1; j <= n; j++) {
|
5646
|
+
let vi = svi[0] + j * this.cols;
|
5647
|
+
for(let j = 1; j <= svi[1]; j++) {
|
5615
5648
|
v_set.push(vbl(vi));
|
5616
5649
|
vi++;
|
5617
5650
|
}
|
5618
5651
|
this.lines += `SOS${sos}: ${v_set.join(',')} <= 2;\n`;
|
5619
|
-
sos++;
|
5620
5652
|
}
|
5621
5653
|
}
|
5622
5654
|
}
|
@@ -5825,19 +5857,18 @@ class VirtualMachine {
|
|
5825
5857
|
if(this.sos_var_indices.length > 0) {
|
5826
5858
|
this.lines += 'SOS\n';
|
5827
5859
|
const abl = this.actualBlockLength(this.block_count);
|
5828
|
-
let sos = 1;
|
5829
5860
|
for(let j = 0; j < abl; j++) {
|
5830
5861
|
for(let i = 0; i < this.sos_var_indices.length; i++) {
|
5831
|
-
|
5832
|
-
|
5833
|
-
|
5834
|
-
for(let j = 1; j <=
|
5835
|
-
const s = ' X' +
|
5862
|
+
const svi = this.sos_var_indices[i];
|
5863
|
+
this.lines += ` S2 sos${i + 1}\n`;
|
5864
|
+
let vi = svi[0] + j * this.cols;
|
5865
|
+
for(let j = 1; j <= svi[1]; j++) {
|
5866
|
+
const s = ' X' +
|
5867
|
+
vi.toString().padStart(this.decimals, '0') +
|
5836
5868
|
' ';
|
5837
5869
|
this.lines += s.substring(0, 15) + j + '\n';
|
5838
5870
|
vi++;
|
5839
5871
|
}
|
5840
|
-
sos++;
|
5841
5872
|
}
|
5842
5873
|
}
|
5843
5874
|
}
|
@@ -6145,7 +6176,7 @@ Solver status = ${json.status}`);
|
|
6145
6176
|
}
|
6146
6177
|
// Diagnosis (by adding slack variables and finite bounds on processes)
|
6147
6178
|
// is activated when Alt-clicking the "run" button, or by clicking the
|
6148
|
-
// "clicke
|
6179
|
+
// "clicke *here* to diagnose" link on the infoline.
|
6149
6180
|
this.diagnose = diagnose || MODEL.always_diagnose;
|
6150
6181
|
if(this.diagnose) {
|
6151
6182
|
this.PLUS_INFINITY = this.DIAGNOSIS_UPPER_BOUND;
|
@@ -6255,11 +6286,26 @@ function VMI_push_block_time(x) {
|
|
6255
6286
|
const
|
6256
6287
|
lt = x.step[x.step.length - 1] - 1,
|
6257
6288
|
bnr = Math.floor(lt / MODEL.block_length),
|
6258
|
-
t = lt - bnr * MODEL.block_length + 1;
|
6289
|
+
t = lt - bnr * MODEL.block_length + 1;
|
6259
6290
|
if(DEBUGGING) console.log('push block time bt = ' + t);
|
6260
6291
|
x.push(t);
|
6261
6292
|
}
|
6262
6293
|
|
6294
|
+
function VMI_push_chunk_time(x) {
|
6295
|
+
// Push the time step for which the VM is preparing the tableau.
|
6296
|
+
// NOTE: Chunk time is meaningful only while the VM is solving a block.
|
6297
|
+
// If not, the block time is pushed.
|
6298
|
+
if(VM.executing_tableau_code) {
|
6299
|
+
const
|
6300
|
+
ct = VM.t - (VM.block_count - 1) * MODEL.block_length;
|
6301
|
+
if(DEBUGGING) console.log('push chunk time ct = ' + ct);
|
6302
|
+
x.push(ct);
|
6303
|
+
} else {
|
6304
|
+
if(DEBUGGING) console.log('push chunk time: NOT constructing tableau');
|
6305
|
+
VMI_push_block_time(x);
|
6306
|
+
}
|
6307
|
+
}
|
6308
|
+
|
6263
6309
|
function VMI_push_block_number(x) {
|
6264
6310
|
// Push the number of the block currently being optimized.
|
6265
6311
|
// NOTE: Block numbering starts at 1.
|
@@ -8329,10 +8375,11 @@ function VMI_set_const_rhs(c) {
|
|
8329
8375
|
}
|
8330
8376
|
|
8331
8377
|
function VMI_set_var_rhs(x) {
|
8378
|
+
VM.rhs = x.result(VM.t);
|
8332
8379
|
if(DEBUGGING) {
|
8333
|
-
console.log(
|
8380
|
+
console.log(`set_var_rhs: ${x.variableName} (t = ${VM.t}) = ` +
|
8381
|
+
VM.sig4Dig(VM.rhs));
|
8334
8382
|
}
|
8335
|
-
VM.rhs = x.result(VM.t);
|
8336
8383
|
}
|
8337
8384
|
|
8338
8385
|
function VMI_add_const_to_rhs(c) {
|
@@ -8669,11 +8716,12 @@ const
|
|
8669
8716
|
SEPARATOR_CHARS = PARENTHESES + OPERATOR_CHARS + "[ '",
|
8670
8717
|
COMPOUND_OPERATORS = ['!=', '<>', '>=', '<='],
|
8671
8718
|
CONSTANT_SYMBOLS = [
|
8672
|
-
't', 'rt', 'bt', 'b', 'N', 'n', 'l', 'r', 'lr', 'nr', 'x', 'nx',
|
8719
|
+
't', 'rt', 'bt', 'ct', 'b', 'N', 'n', 'l', 'r', 'lr', 'nr', 'x', 'nx',
|
8673
8720
|
'random', 'dt', 'true', 'false', 'pi', 'infinity', '#',
|
8674
8721
|
'i', 'j', 'k', 'yr', 'wk', 'd', 'h', 'm', 's'],
|
8675
8722
|
CONSTANT_CODES = [
|
8676
8723
|
VMI_push_time_step, VMI_push_relative_time, VMI_push_block_time,
|
8724
|
+
VMI_push_chunk_time,
|
8677
8725
|
VMI_push_block_number, VMI_push_run_length, VMI_push_block_length,
|
8678
8726
|
VMI_push_look_ahead, VMI_push_round, VMI_push_last_round,
|
8679
8727
|
VMI_push_number_of_rounds, VMI_push_run_number, VMI_push_number_of_runs,
|
@@ -8682,7 +8730,7 @@ const
|
|
8682
8730
|
VMI_push_i, VMI_push_j, VMI_push_k,
|
8683
8731
|
VMI_push_year, VMI_push_week, VMI_push_day, VMI_push_hour,
|
8684
8732
|
VMI_push_minute, VMI_push_second],
|
8685
|
-
DYNAMIC_SYMBOLS = ['t', 'rt', 'bt', 'b', 'r', 'random', 'i', 'j', 'k'],
|
8733
|
+
DYNAMIC_SYMBOLS = ['t', 'rt', 'bt', 'ct', 'b', 'r', 'random', 'i', 'j', 'k'],
|
8686
8734
|
MONADIC_OPERATORS = [
|
8687
8735
|
'~', 'not', 'abs', 'sin', 'cos', 'atan', 'ln',
|
8688
8736
|
'exp', 'sqrt', 'round', 'int', 'fract', 'min', 'max',
|