mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-10 10:25:36 +01:00
experiments
This commit is contained in:
parent
888c1efb61
commit
bdd886571f
2 changed files with 186 additions and 0 deletions
177
web/app/math/foptim.js
Normal file
177
web/app/math/foptim.js
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
// this is Gauss-Newton least square algorithm with trust region(dog leg) control/
|
||||
//
|
||||
optim.dog_leg = function(subsys) {
|
||||
|
||||
var tolg=1e-80, tolx=1e-80, tolf=1e-10;
|
||||
|
||||
var xsize = subsys.params.length;
|
||||
var csize = subsys.constraints.length;
|
||||
|
||||
if (xsize == 0)
|
||||
return 'Success';
|
||||
|
||||
var vec = TCAD.math._arr;
|
||||
var mx = TCAD.math._matrix;
|
||||
|
||||
var n = numeric;
|
||||
|
||||
var x = vec(xsize);
|
||||
var x_new = vec(xsize);
|
||||
|
||||
var fx = vec(csize);
|
||||
var fx_new = vec(csize);
|
||||
|
||||
var Jx = mx(csize, xsize);
|
||||
var Jx_new = mx(csize, xsize);
|
||||
var g = vec(xsize);
|
||||
var h_sd = vec(xsize);
|
||||
var h_gn = vec(xsize);
|
||||
var h_dl = vec(xsize);
|
||||
|
||||
var r0 = vec(csize);
|
||||
|
||||
var err;
|
||||
subsys.fillParams(x);
|
||||
|
||||
err = subsys.calcResidual(fx);
|
||||
subsys.fillJacobian(Jx);
|
||||
|
||||
function lsolve(A, b) {
|
||||
var At = n.transpose(A);
|
||||
var res = n.dot(n.dot(At, n.inv(n.dot(A, At)) ), b);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
g = n.dot(n.transpose(Jx), n.mul(fx, -1));
|
||||
|
||||
// get the infinity norm fx_inf and g_inf
|
||||
var g_inf = n.norminf(g);
|
||||
var fx_inf = n.norminf(fx);
|
||||
|
||||
var maxIterNumber = 100 * xsize;
|
||||
var divergingLim = 1e6*err + 1e12;
|
||||
|
||||
var delta=0.1;
|
||||
var alpha=0.;
|
||||
var nu=2.;
|
||||
var iter=0, stop=0, reduce=0;
|
||||
while (!stop) {
|
||||
|
||||
// check if finished
|
||||
if (fx_inf <= tolf) // Success
|
||||
stop = 1;
|
||||
else if (g_inf <= tolg)
|
||||
stop = 2;
|
||||
else if (delta <= tolx*(tolx + n.norm2(x)))
|
||||
stop = 2;
|
||||
else if (iter >= maxIterNumber)
|
||||
stop = 4;
|
||||
else if (err > divergingLim || err != err) { // check for diverging and NaN
|
||||
stop = 6;
|
||||
}
|
||||
else {
|
||||
// get the steepest descent direction
|
||||
alpha = n.norm2Squared(g)/n.norm2Squared(n.dot(Jx, g));
|
||||
h_sd = n.mul(g, alpha);
|
||||
|
||||
// get the gauss-newton step
|
||||
// h_gn = n.solve(Jx, n.mul(fx, -1));
|
||||
h_gn = lsolve(Jx, n.mul(fx, -1));
|
||||
|
||||
// solve linear problem using svd formula to get the gauss-newton step
|
||||
// h_gn = lls(Jx, n.mul(fx, -1));
|
||||
|
||||
var rel_error = n.norm2(n.add(n.dot(Jx, h_gn), fx)) / n.norm2(fx);
|
||||
if (rel_error > 1e15)
|
||||
break;
|
||||
|
||||
// compute the dogleg step
|
||||
if (n.norm2(h_gn) < delta) {
|
||||
h_dl = n.clone(h_gn);
|
||||
if (n.norm2(h_dl) <= tolx*(tolx + n.norm2(x))) {
|
||||
stop = 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (alpha*n.norm2(g) >= delta) {
|
||||
h_dl = n.mul( h_sd, delta/(alpha*n.norm2(g)));
|
||||
}
|
||||
else {
|
||||
//compute beta
|
||||
var beta = 0;
|
||||
var b = n.sub(h_gn, h_sd);
|
||||
var bb = Math.abs(n.dot(b, b));
|
||||
var gb = Math.abs(n.dot(h_sd,b));
|
||||
var c = (delta + n.norm2(h_sd))*(delta - n.norm2(h_sd));
|
||||
|
||||
if (gb > 0)
|
||||
beta = c / (gb + Math.sqrt(gb * gb + c * bb));
|
||||
else
|
||||
beta = (Math.sqrt(gb * gb + c * bb) - gb)/bb;
|
||||
|
||||
// and update h_dl and dL with beta
|
||||
h_dl = n.add(h_sd, n.mul(beta,b));
|
||||
}
|
||||
}
|
||||
|
||||
// see if we are already finished
|
||||
if (stop)
|
||||
break;
|
||||
|
||||
// it didn't work in some tests
|
||||
// // restrict h_dl according to maxStep
|
||||
// double scale = subsys->maxStep(h_dl);
|
||||
// if (scale < 1.)
|
||||
// h_dl *= scale;
|
||||
|
||||
// get the new values
|
||||
var err_new;
|
||||
x_new = n.add(x, h_dl);
|
||||
subsys.setParams(x_new);
|
||||
err_new = subsys.calcResidual(fx_new);
|
||||
subsys.fillJacobian(Jx_new);
|
||||
|
||||
// calculate the linear model and the update ratio
|
||||
var dL = err - 0.5* n.norm2Squared(n.add(fx, n.dot(Jx, h_dl)));
|
||||
var dF = err - err_new;
|
||||
var rho = dL/dF;
|
||||
|
||||
if (dF > 0 && dL > 0) {
|
||||
x = n.clone(x_new);
|
||||
Jx = n.clone(Jx_new);
|
||||
fx = n.clone(fx_new);
|
||||
err = err_new;
|
||||
|
||||
g = n.dot(n.transpose(Jx), n.mul(fx, -1));
|
||||
|
||||
// get infinity norms
|
||||
g_inf = n.norminf(g);
|
||||
fx_inf = n.norminf(fx);
|
||||
}
|
||||
else
|
||||
rho = -1;
|
||||
|
||||
// update delta
|
||||
if (Math.abs(rho-1.) < 0.2 && n.norm2(h_dl) > delta/3. && reduce <= 0) {
|
||||
delta = 3*delta;
|
||||
nu = 2;
|
||||
reduce = 0;
|
||||
}
|
||||
else if (rho < 0.25) {
|
||||
delta = delta/nu;
|
||||
nu = 2*nu;
|
||||
reduce = 2;
|
||||
}
|
||||
else
|
||||
reduce--;
|
||||
|
||||
// count this iteration and start again
|
||||
iter++;
|
||||
}
|
||||
|
||||
|
||||
return (stop == 1) ? 'Success' : 'Failed';
|
||||
|
||||
};
|
||||
|
||||
9
web/app/ui.js
Normal file
9
web/app/ui.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
TCAD.ui = {};
|
||||
|
||||
TCAD.ui.list = function(model) {
|
||||
|
||||
};
|
||||
|
||||
TCAD.ui.list.prototype.refresh = function() {
|
||||
|
||||
};
|
||||
Loading…
Reference in a new issue