linny-r 1.7.3 → 1.7.4

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.
@@ -8938,6 +8938,12 @@ class Dataset {
8938
8938
  return this.vector;
8939
8939
  }
8940
8940
  if(a === '.') return this.vector;
8941
+ // Still permit legacy use of [dataset|attr] as a way to "call" a
8942
+ // dataset modifier expression explicitly.
8943
+ if(a) {
8944
+ const x = this.attributeExpression(a);
8945
+ if(x) return x.result(MODEL.t);
8946
+ }
8941
8947
  // Fall-through: return the default value of this dataset.
8942
8948
  return this.defaultValue;
8943
8949
  }
@@ -9384,11 +9390,15 @@ class ChartVariable {
9384
9390
  t_end = tsteps;
9385
9391
  } else {
9386
9392
  // Get the variable's own value (number, vector or expression)
9387
- if(this.object instanceof Dataset && !this.attribute) {
9388
- // Special case: Variables that depict a dataset with no explicit
9389
- // modifier selector must recompute the vector using the current
9390
- // experiment run combination or the default selector.
9391
- av = this.object.activeModifierExpression;
9393
+ if(this.object instanceof Dataset) {
9394
+ if(this.attribute) {
9395
+ av = this.object.attributeExpression(this.attribute);
9396
+ } else {
9397
+ // Special case: Variables that depict a dataset with no explicit
9398
+ // modifier selector must recompute the vector using the current
9399
+ // experiment run combination or the default selector.
9400
+ av = this.object.activeModifierExpression;
9401
+ }
9392
9402
  } else if(this.object instanceof DatasetModifier) {
9393
9403
  av = this.object.expression;
9394
9404
  } else {
@@ -12024,7 +12034,7 @@ class Experiment {
12024
12034
  class BoundLine {
12025
12035
  constructor(c) {
12026
12036
  this.constraint = c;
12027
- // Default bound line imposes no constraint: Y >= 0 for all X
12037
+ // Default bound line imposes no constraint: Y >= 0 for all X.
12028
12038
  this.points = [[0, 0], [100, 0]];
12029
12039
  this.type = VM.GE;
12030
12040
  this.selectors = '';
@@ -12039,7 +12049,7 @@ class BoundLine {
12039
12049
  }
12040
12050
 
12041
12051
  get copy() {
12042
- // Returns a "clone" of this bound line
12052
+ // Return a "clone" of this bound line.
12043
12053
  let bl = new BoundLine(this.constraint);
12044
12054
  bl.points.length = 0;
12045
12055
  for(let i = 0; i < this.points.length; i++) {
@@ -12068,8 +12078,8 @@ class BoundLine {
12068
12078
  }
12069
12079
 
12070
12080
  get isActive() {
12071
- // Returns TRUE if this line has no selectors, or if its selectors match
12072
- // with the selectors of the current experiment run
12081
+ // Return TRUE if this line has no selectors, or if its selectors match
12082
+ // with the selectors of the current experiment run.
12073
12083
  if(!this.selectors) return true;
12074
12084
  const x = MODEL.running_experiment;
12075
12085
  if(!x) return false;
@@ -12077,12 +12087,49 @@ class BoundLine {
12077
12087
  return ss.length > 0;
12078
12088
  }
12079
12089
 
12090
+ get needsNoSOS() {
12091
+ // Return 1 if boundline is NOT of type <= and line segments have an
12092
+ // increasing slope, -1 if boundline is NOT of type >= and line segments
12093
+ // have a decreasing slope, and otherwise 0 (FALSE). If non-zero (TRUE),
12094
+ // the constraint can be implemented without the SOS2 constraint that
12095
+ // only two consecutive SOS variables may be non-zero.
12096
+ if(this.type !== VM.LE) {
12097
+ let slope = 0,
12098
+ pp = this.points[0];
12099
+ for(let i = 1; i < this.points.length; i++) {
12100
+ const
12101
+ p = this.points[i],
12102
+ dx = p[0] - pp[0],
12103
+ s = (dx <= VM.NEAR_ZERO ? VM.PLUS_INFINITY : (p[1] - pp[1]) / dx);
12104
+ // Decreasing slope => not convex.
12105
+ if(s < slope) return 0;
12106
+ slope = s;
12107
+ }
12108
+ return 1;
12109
+ } else if (this.type !== VM.GE) {
12110
+ let slope = VM.PLUS_INFINITY,
12111
+ pp = this.points[0];
12112
+ for(let i = 1; i < this.points.length; i++) {
12113
+ const
12114
+ p = this.points[i],
12115
+ dx = p[0] - pp[0],
12116
+ s = (dx <= VM.NEAR_ZERO ? VM.PLUS_INFINITY : (p[1] - pp[1]) / dx);
12117
+ // Increasing slope => not convex.
12118
+ if(s > slope) return 0;
12119
+ slope = s;
12120
+ }
12121
+ return -1;
12122
+ }
12123
+ // Fall-through (should not occur).
12124
+ return 0;
12125
+ }
12126
+
12080
12127
  get constrainsY() {
12081
- // Returns TRUE if this bound line constrains Y in some way
12128
+ // Return TRUE if this bound line constrains Y in some way.
12082
12129
  if(this.type === VM.EQ) return true;
12083
12130
  for(let j = 0; j < this.points.length; j++) {
12084
12131
  const p = this.points[j];
12085
- // LE bound line constrains when not at 100%, GE when not at 0%
12132
+ // LE bound line constrains when not at 100%, GE when not at 0%.
12086
12133
  if(this.type === VM.LE && p[1] < 100 || this.type === VM.GE && p[1] > 0) {
12087
12134
  return true;
12088
12135
  }
@@ -12091,8 +12138,8 @@ class BoundLine {
12091
12138
  }
12092
12139
 
12093
12140
  pointOnLine(x, y) {
12094
- // Returns TRUE iff (x, y) lies on this bound line (+/- 0.001%)
12095
- // or within radius < tolerance from a point
12141
+ // Return TRUE iff (x, y) lies on this bound line (+/- 0.001%)
12142
+ // or within radius < tolerance from a point.
12096
12143
  const
12097
12144
  tol = 0.001,
12098
12145
  tolsq = tol * tol;
@@ -12107,27 +12154,27 @@ class BoundLine {
12107
12154
  if(x > pp[0] - 1 && x < p[0] + 1 &&
12108
12155
  ((y > pp[1] - tol && y < p[1] + tol) ||
12109
12156
  (y < pp[1] + tol && y > p[1] + tol))) {
12110
- // Cursor lies within rectangle around line segment
12157
+ // Cursor lies within rectangle around line segment.
12111
12158
  const
12112
12159
  dx = p[0] - pp[0],
12113
12160
  dy = p[1] - pp[1];
12114
12161
  if(Math.abs(dx) < tol || Math.abs(dy) < tol) {
12115
- // Special case: (near) vertical or (near) horizontal line
12162
+ // Special case: (near) vertical or (near) horizontal line.
12116
12163
  return true;
12117
12164
  } else {
12118
- // Compute horizontal & vertical distance to line segment
12165
+ // Compute horizontal & vertical distance to line segment.
12119
12166
  const
12120
- // H & V distance from left-most point
12167
+ // H & V distance from left-most point.
12121
12168
  dpx = x - pp[0],
12122
12169
  dpy = y - pp[1],
12123
- // Projected X, given Y-distance
12170
+ // Projected X, given Y-distance.
12124
12171
  nx = pp[0] + dpy * dx / dy,
12125
- // Projected Y, given X-distance
12172
+ // Projected Y, given X-distance.
12126
12173
  ny = pp[1] + dpx * dy / dx,
12127
- // Take absolute differences
12174
+ // Take absolute differences.
12128
12175
  dxol = Math.abs(nx - x),
12129
12176
  dyol = Math.abs(ny - y);
12130
- // Only test the shortest distance
12177
+ // Only test the shortest distance.
12131
12178
  if (Math.min(dxol, dyol) < tol) {
12132
12179
  return true;
12133
12180
  }