linny-r 1.9.1 → 1.9.3
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/scripts/linny-r-model.js +43 -35
- package/static/scripts/linny-r-vm.js +25 -13
package/package.json
CHANGED
@@ -3471,8 +3471,9 @@ class LinnyRModel {
|
|
3471
3471
|
let n = 0;
|
3472
3472
|
for(let i = 0; i < constraints.length; i++) {
|
3473
3473
|
const c = constraints[i];
|
3474
|
-
if(
|
3475
|
-
(c.
|
3474
|
+
if(!MODEL.ignored_entities[c.identifier] &&
|
3475
|
+
((c.to_node === p && c.soc_direction === VM.SOC_X_Y) ||
|
3476
|
+
(c.from_node === p && c.soc_direction === VM.SOC_Y_X))) n++;
|
3476
3477
|
}
|
3477
3478
|
return n;
|
3478
3479
|
},
|
@@ -3484,7 +3485,8 @@ class LinnyRModel {
|
|
3484
3485
|
for(let i = 0; i < p.inputs.length; i++) {
|
3485
3486
|
const l = p.inputs[i];
|
3486
3487
|
// NOTE: Only process --> product links can carry cost.
|
3487
|
-
if(l.
|
3488
|
+
if(!MODEL.ignored_entities[l.identifier] &&
|
3489
|
+
l.from_node instanceof Process) {
|
3488
3490
|
tuple.n++;
|
3489
3491
|
if(l.share_of_cost === 0) tuple.nosoc++;
|
3490
3492
|
const d = l.actualDelay(t);
|
@@ -3656,12 +3658,15 @@ class LinnyRModel {
|
|
3656
3658
|
const p = processes[i];
|
3657
3659
|
let cp = 0;
|
3658
3660
|
for(let j = 0; j < p.inputs.length; j++) {
|
3659
|
-
const
|
3660
|
-
if(
|
3661
|
-
|
3662
|
-
|
3663
|
-
|
3664
|
-
|
3661
|
+
const l = p.inputs[j];
|
3662
|
+
if(!MODEL.ignored_entities[l.identifier]) {
|
3663
|
+
const ucp = l.unit_cost_price;
|
3664
|
+
if(ucp === VM.UNDEFINED) {
|
3665
|
+
cp = VM.UNDEFINED;
|
3666
|
+
break;
|
3667
|
+
} else {
|
3668
|
+
cp += ucp;
|
3669
|
+
}
|
3665
3670
|
}
|
3666
3671
|
}
|
3667
3672
|
// NOTE: Also check constraints that transfer cost to `p`.
|
@@ -3682,31 +3687,33 @@ class LinnyRModel {
|
|
3682
3687
|
// NOTE: ignore SoC, as this affects the CP of the product, but
|
3683
3688
|
// NOT the CP of the process producing it.
|
3684
3689
|
for(let j = 0; j < p.outputs.length; j++) {
|
3685
|
-
const
|
3686
|
-
|
3687
|
-
|
3688
|
-
|
3689
|
-
|
3690
|
-
|
3691
|
-
|
3692
|
-
|
3693
|
-
|
3694
|
-
|
3695
|
-
|
3696
|
-
|
3697
|
-
|
3698
|
-
|
3699
|
-
|
3700
|
-
|
3701
|
-
|
3702
|
-
|
3703
|
-
|
3704
|
-
|
3705
|
-
|
3706
|
-
|
3707
|
-
|
3708
|
-
|
3709
|
-
|
3690
|
+
const l = p.outputs[j];
|
3691
|
+
if(!MODEL.ignored_entities[l.identifier]) {
|
3692
|
+
const
|
3693
|
+
// NOTE: For output links always use current price.
|
3694
|
+
px = l.to_node.price,
|
3695
|
+
pr = (px.defined ? px.result(t) : 0),
|
3696
|
+
// For levels, consider delay: earlier if delay > 0.
|
3697
|
+
dt = t - l.actualDelay(t);
|
3698
|
+
if(pr < 0) {
|
3699
|
+
// Only consider negative prices.
|
3700
|
+
if(l.multiplier === VM.LM_LEVEL) {
|
3701
|
+
// Treat links with level multiplier similar to input links,
|
3702
|
+
// as this computes CP even when actual level = 0.
|
3703
|
+
// NOTE: Subtract (!) so as to ADD the cost.
|
3704
|
+
cp -= pr * l.relative_rate.result(dt);
|
3705
|
+
} else {
|
3706
|
+
// For other types, multiply price by actual flow / level
|
3707
|
+
// NOTE: actualFlow already considers delay => use t, not dt.
|
3708
|
+
const af = l.actualFlow(t);
|
3709
|
+
if(af > VM.NEAR_ZERO) {
|
3710
|
+
// Prevent division by zero.
|
3711
|
+
// NOTE: Level can be zero even if actual flow > 0!
|
3712
|
+
let al = p.nonZeroLevel(dt, l.multiplier);
|
3713
|
+
// NOTE: Scale to level only when level > 1, or fixed
|
3714
|
+
// costs for start-up or first commit will be amplified.
|
3715
|
+
if(al > VM.NEAR_ZERO) cp -= pr * af / Math.max(al, 1);
|
3716
|
+
}
|
3710
3717
|
}
|
3711
3718
|
}
|
3712
3719
|
}
|
@@ -3767,7 +3774,8 @@ class LinnyRModel {
|
|
3767
3774
|
cp_sccp = VM.COMPUTING;
|
3768
3775
|
for(let j = 0; j < p.inputs.length; j++) {
|
3769
3776
|
const l = p.inputs[j];
|
3770
|
-
if(l.
|
3777
|
+
if(!MODEL.ignored_entities[l.identifier] &&
|
3778
|
+
l.from_node instanceof Process) {
|
3771
3779
|
cp = l.from_node.costPrice(t - l.actualDelay(t));
|
3772
3780
|
if(cp === VM.UNDEFINED && l.share_of_cost > 0) {
|
3773
3781
|
// Contributing CP still unknown => break from FOR loop.
|
@@ -2567,7 +2567,7 @@ class VirtualMachine {
|
|
2567
2567
|
return Math.round(n);
|
2568
2568
|
}
|
2569
2569
|
|
2570
|
-
sig4Dig(n) {
|
2570
|
+
sig4Dig(n, tiny=false) {
|
2571
2571
|
// Return number `n` formatted so as to show 4-5 significant digits.
|
2572
2572
|
// NOTE: As `n` should be a number, a warning sign will typically
|
2573
2573
|
// indicate a bug in the software.
|
@@ -2576,8 +2576,13 @@ class VirtualMachine {
|
|
2576
2576
|
// If `n` has a special value, return its representation.
|
2577
2577
|
if(sv[0]) return sv[1];
|
2578
2578
|
const a = Math.abs(n);
|
2579
|
+
if(a === 0) return 0;
|
2579
2580
|
// Signal small differences from true 0 by a leading + or - sign.
|
2580
|
-
if(
|
2581
|
+
if(a <= this.ON_OFF_THRESHOLD) {
|
2582
|
+
// The `tiny` flag indicates: display small number in E-notation.
|
2583
|
+
if(tiny) return n.toPrecision(1);
|
2584
|
+
return n > 0 ? '+0' : '-0';
|
2585
|
+
}
|
2581
2586
|
if(a >= 9999995) return n.toPrecision(4);
|
2582
2587
|
if(Math.abs(a-Math.round(a)) < 0.0005) return Math.round(n);
|
2583
2588
|
if(a < 1) return Math.round(n*10000) / 10000;
|
@@ -4666,7 +4671,9 @@ class VirtualMachine {
|
|
4666
4671
|
}
|
4667
4672
|
if(b <= this.nr_of_time_steps && absl > VM.ON_OFF_THRESHOLD) {
|
4668
4673
|
this.logMessage(block, `${this.WARNING}(t=${b}${round}) ` +
|
4669
|
-
`${v[1].displayName} ${v[0]} slack =
|
4674
|
+
`${v[1].displayName} ${v[0]} slack = ` +
|
4675
|
+
// NOTE: TRUE denotes "show tiny values with precision".
|
4676
|
+
this.sig4Dig(slack, true));
|
4670
4677
|
if(v[1] instanceof Product) {
|
4671
4678
|
const ppc = v[1].productPositionClusters;
|
4672
4679
|
for(let ci = 0; ci < ppc.length; ci++) {
|
@@ -6582,28 +6589,32 @@ function relativeTimeStep(t, anchor, offset, dtm, x) {
|
|
6582
6589
|
// Offset relative to current time step, scaled to time unit of run.
|
6583
6590
|
return Math.floor((t + offset) * dtm);
|
6584
6591
|
}
|
6592
|
+
if(anchor === 'f') {
|
6593
|
+
// Last: offset relative to index 1 in the vector.
|
6594
|
+
return 1 + offset;
|
6595
|
+
}
|
6596
|
+
if(anchor === 'l') {
|
6597
|
+
// Last: offset relative to the last index in the vector.
|
6598
|
+
return VM.nr_of_time_steps + offset;
|
6599
|
+
}
|
6600
|
+
const cb = Math.trunc((t - 1) / MODEL.block_length);
|
6585
6601
|
if(anchor === 'c') {
|
6586
6602
|
// Relative to start of current optimization block.
|
6587
|
-
return
|
6603
|
+
return cb * MODEL.block_length + 1 + offset;
|
6588
6604
|
}
|
6589
6605
|
if(anchor === 'p') {
|
6590
6606
|
// Relative to start of previous optimization block.
|
6591
|
-
return (
|
6607
|
+
return (cb - 1) * MODEL.block_length + 1 + offset;
|
6592
6608
|
}
|
6593
6609
|
if(anchor === 'n') {
|
6594
6610
|
// Relative to start of next optimization block.
|
6595
|
-
return (
|
6596
|
-
}
|
6597
|
-
if(anchor === 'l') {
|
6598
|
-
// Last: offset relative to the last index in the vector.
|
6599
|
-
return VM.nr_of_time_steps + offset;
|
6611
|
+
return (cb + 1) * MODEL.block_length + 1 + offset;
|
6600
6612
|
}
|
6601
6613
|
if(anchor === 's') {
|
6602
6614
|
// Scaled: offset is scaled to time unit of run.
|
6603
6615
|
return Math.floor(offset * dtm);
|
6604
6616
|
}
|
6605
6617
|
// Fall-through: offset relative to the initial value index (0).
|
6606
|
-
// NOTE: this also applies to anchor f (First).
|
6607
6618
|
return offset;
|
6608
6619
|
}
|
6609
6620
|
|
@@ -7121,7 +7132,8 @@ function VMI_push_statistic(x, args) {
|
|
7121
7132
|
t2 = Math.max(0, Math.min(tmax, t2));
|
7122
7133
|
// Trace only now that time step range has been computed
|
7123
7134
|
if(DEBUGGING) {
|
7124
|
-
const trc = ['push statistic: [', stat, ': N = ', list.length, ']',
|
7135
|
+
const trc = ['push statistic: [', stat, ': N = ', list.length, ']',
|
7136
|
+
ao1, ao2, ' (t = ', t1, '-', t2, ')'];
|
7125
7137
|
console.log(trc.join(''));
|
7126
7138
|
}
|
7127
7139
|
// Establish whether statistic pertains to non-zero values only
|
@@ -7157,7 +7169,7 @@ function VMI_push_statistic(x, args) {
|
|
7157
7169
|
const
|
7158
7170
|
n = vlist.length,
|
7159
7171
|
// NOTE: count is the number of values used in the statistic
|
7160
|
-
count = (nz ? n : list.length);
|
7172
|
+
count = (nz ? n : list.length * (t2 - t1 + 1));
|
7161
7173
|
if(stat === 'N') {
|
7162
7174
|
x.push(count);
|
7163
7175
|
return;
|