StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
4.9 KiB
190 lines
4.9 KiB
"use strict"
|
|
|
|
var twoProduct = require("two-product")
|
|
var robustSum = require("robust-sum")
|
|
var robustScale = require("robust-scale")
|
|
var robustSubtract = require("robust-subtract")
|
|
|
|
var NUM_EXPAND = 5
|
|
|
|
var EPSILON = 1.1102230246251565e-16
|
|
var ERRBOUND3 = (3.0 + 16.0 * EPSILON) * EPSILON
|
|
var ERRBOUND4 = (7.0 + 56.0 * EPSILON) * EPSILON
|
|
|
|
function cofactor(m, c) {
|
|
var result = new Array(m.length-1)
|
|
for(var i=1; i<m.length; ++i) {
|
|
var r = result[i-1] = new Array(m.length-1)
|
|
for(var j=0,k=0; j<m.length; ++j) {
|
|
if(j === c) {
|
|
continue
|
|
}
|
|
r[k++] = m[i][j]
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
function matrix(n) {
|
|
var result = new Array(n)
|
|
for(var i=0; i<n; ++i) {
|
|
result[i] = new Array(n)
|
|
for(var j=0; j<n; ++j) {
|
|
result[i][j] = ["m", j, "[", (n-i-1), "]"].join("")
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
function sign(n) {
|
|
if(n & 1) {
|
|
return "-"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
function generateSum(expr) {
|
|
if(expr.length === 1) {
|
|
return expr[0]
|
|
} else if(expr.length === 2) {
|
|
return ["sum(", expr[0], ",", expr[1], ")"].join("")
|
|
} else {
|
|
var m = expr.length>>1
|
|
return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("")
|
|
}
|
|
}
|
|
|
|
function determinant(m) {
|
|
if(m.length === 2) {
|
|
return [["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("")]
|
|
} else {
|
|
var expr = []
|
|
for(var i=0; i<m.length; ++i) {
|
|
expr.push(["scale(", generateSum(determinant(cofactor(m, i))), ",", sign(i), m[0][i], ")"].join(""))
|
|
}
|
|
return expr
|
|
}
|
|
}
|
|
|
|
function orientation(n) {
|
|
var pos = []
|
|
var neg = []
|
|
var m = matrix(n)
|
|
var args = []
|
|
for(var i=0; i<n; ++i) {
|
|
if((i&1)===0) {
|
|
pos.push.apply(pos, determinant(cofactor(m, i)))
|
|
} else {
|
|
neg.push.apply(neg, determinant(cofactor(m, i)))
|
|
}
|
|
args.push("m" + i)
|
|
}
|
|
var posExpr = generateSum(pos)
|
|
var negExpr = generateSum(neg)
|
|
var funcName = "orientation" + n + "Exact"
|
|
var code = ["function ", funcName, "(", args.join(), "){var p=", posExpr, ",n=", negExpr, ",d=sub(p,n);\
|
|
return d[d.length-1];};return ", funcName].join("")
|
|
var proc = new Function("sum", "prod", "scale", "sub", code)
|
|
return proc(robustSum, twoProduct, robustScale, robustSubtract)
|
|
}
|
|
|
|
var orientation3Exact = orientation(3)
|
|
var orientation4Exact = orientation(4)
|
|
|
|
var CACHED = [
|
|
function orientation0() { return 0 },
|
|
function orientation1() { return 0 },
|
|
function orientation2(a, b) {
|
|
return b[0] - a[0]
|
|
},
|
|
function orientation3(a, b, c) {
|
|
var l = (a[1] - c[1]) * (b[0] - c[0])
|
|
var r = (a[0] - c[0]) * (b[1] - c[1])
|
|
var det = l - r
|
|
var s
|
|
if(l > 0) {
|
|
if(r <= 0) {
|
|
return det
|
|
} else {
|
|
s = l + r
|
|
}
|
|
} else if(l < 0) {
|
|
if(r >= 0) {
|
|
return det
|
|
} else {
|
|
s = -(l + r)
|
|
}
|
|
} else {
|
|
return det
|
|
}
|
|
var tol = ERRBOUND3 * s
|
|
if(det >= tol || det <= -tol) {
|
|
return det
|
|
}
|
|
return orientation3Exact(a, b, c)
|
|
},
|
|
function orientation4(a,b,c,d) {
|
|
var adx = a[0] - d[0]
|
|
var bdx = b[0] - d[0]
|
|
var cdx = c[0] - d[0]
|
|
var ady = a[1] - d[1]
|
|
var bdy = b[1] - d[1]
|
|
var cdy = c[1] - d[1]
|
|
var adz = a[2] - d[2]
|
|
var bdz = b[2] - d[2]
|
|
var cdz = c[2] - d[2]
|
|
var bdxcdy = bdx * cdy
|
|
var cdxbdy = cdx * bdy
|
|
var cdxady = cdx * ady
|
|
var adxcdy = adx * cdy
|
|
var adxbdy = adx * bdy
|
|
var bdxady = bdx * ady
|
|
var det = adz * (bdxcdy - cdxbdy)
|
|
+ bdz * (cdxady - adxcdy)
|
|
+ cdz * (adxbdy - bdxady)
|
|
var permanent = (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz)
|
|
+ (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz)
|
|
+ (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz)
|
|
var tol = ERRBOUND4 * permanent
|
|
if ((det > tol) || (-det > tol)) {
|
|
return det
|
|
}
|
|
return orientation4Exact(a,b,c,d)
|
|
}
|
|
]
|
|
|
|
function slowOrient(args) {
|
|
var proc = CACHED[args.length]
|
|
if(!proc) {
|
|
proc = CACHED[args.length] = orientation(args.length)
|
|
}
|
|
return proc.apply(undefined, args)
|
|
}
|
|
|
|
function generateOrientationProc() {
|
|
while(CACHED.length <= NUM_EXPAND) {
|
|
CACHED.push(orientation(CACHED.length))
|
|
}
|
|
var args = []
|
|
var procArgs = ["slow"]
|
|
for(var i=0; i<=NUM_EXPAND; ++i) {
|
|
args.push("a" + i)
|
|
procArgs.push("o" + i)
|
|
}
|
|
var code = [
|
|
"function getOrientation(", args.join(), "){switch(arguments.length){case 0:case 1:return 0;"
|
|
]
|
|
for(var i=2; i<=NUM_EXPAND; ++i) {
|
|
code.push("case ", i, ":return o", i, "(", args.slice(0, i).join(), ");")
|
|
}
|
|
code.push("}var s=new Array(arguments.length);for(var i=0;i<arguments.length;++i){s[i]=arguments[i]};return slow(s);}return getOrientation")
|
|
procArgs.push(code.join(""))
|
|
|
|
var proc = Function.apply(undefined, procArgs)
|
|
module.exports = proc.apply(undefined, [slowOrient].concat(CACHED))
|
|
for(var i=0; i<=NUM_EXPAND; ++i) {
|
|
module.exports[i] = CACHED[i]
|
|
}
|
|
}
|
|
|
|
generateOrientationProc() |