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.
- package/README.md +23 -12
- package/console.js +2 -2
- package/package.json +1 -1
- package/server.js +2 -2
- package/static/index.html +1 -0
- package/static/linny-r.css +10 -1
- package/static/scripts/linny-r-ctrl.js +1 -1
- package/static/scripts/linny-r-gui-constraint-editor.js +15 -2
- package/static/scripts/linny-r-gui-controller.js +6 -3
- package/static/scripts/linny-r-gui-equation-manager.js +6 -6
- package/static/scripts/linny-r-gui-expression-editor.js +6 -3
- package/static/scripts/linny-r-gui-finder.js +1 -1
- package/static/scripts/linny-r-gui-monitor.js +5 -5
- package/static/scripts/linny-r-milp.js +263 -81
- package/static/scripts/linny-r-model.js +68 -21
- package/static/scripts/linny-r-vm.js +263 -101
@@ -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
|
9388
|
-
|
9389
|
-
|
9390
|
-
|
9391
|
-
|
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
|
-
//
|
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
|
-
//
|
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
|
-
//
|
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
|
-
//
|
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
|
}
|