gradientSteps = (initX = 0.6, initY = 0.4, t = 0.5) => {
const { ctx } = canvasStuff,
trace = [],
traceNewton = [],
scaleX = d3.scaleLinear().domain([0, 1]).range([0, width]),
scaleY = d3.scaleLinear().domain([0, 1]).range([0, height]);
{
var x = initX,
y = initY,
dx,
dy,
n = 100;
trace.push(Object.assign({}, { r: 0, i: 0, x, y }));
for (let i = 1; i < n + 1; ++i) {
dx = dfdx(x, y, t) * unitX;
dy = dfdy(x, y, t) * unitX;
x -= dx;
y -= dy;
trace.push(Object.assign({}, { r: i / n, i, x, y }));
}
}
{
var x = initX,
y = initY,
dx,
dy,
grad,
alpha,
d2xx,
d2xy,
d2yx,
d2yy,
hessian,
hessianInv,
dxdy,
d,
n = 10;
traceNewton.push(Object.assign({}, { r: 0, i: 0, x, y }));
for (let i = 1; i < n; ++i) {
d2xx = d2fdxdx(x, y, t);
d2xy = d2fdxdy(x, y, t);
d2yx = d2fdydx(x, y, t);
d2yy = d2fdydy(x, y, t);
dx = dfdx(x, y, t);
dy = dfdy(x, y, t);
grad = new ML.Matrix([[dx], [dy]]);
hessian = new ML.Matrix([
[d2xx, d2xy],
[d2yx, d2yy]
]);
if (false) {
hessianInv = ML.inverse(hessian);
dxdy = hessianInv.mmul(grad).data.map((d) => d[0]);
d = mkGrad(dxdy[0], dxdy[1]);
x -= d.dx; //dxdy[0];
y -= d.dy; //dxdy[1];
}
{
alpha =
grad.transpose().mmul(grad).data[0][0] /
grad.transpose().mmul(hessian).mmul(grad).data[0][0];
alpha = Math.abs(alpha);
// alpha = -alpha;
if (alpha > 0) {
x -= dx * alpha;
y -= dy * alpha;
}
}
traceNewton.push(Object.assign({}, { r: i / n, i, x, y }));
}
}
// const drawPnt = ({ r, i, x, y }) => {
// ctx.beginPath();
// ctx.rect(scaleX(x), scaleY(y), 3, 3);
// ctx.fillStyle = d3.interpolateWarm(r); //"white";
// ctx.fill();
// };
// trace.map((d) => drawPnt(d));
if (checkboxes.includes("Grad")) {
for (let i = 1; i < trace.length; ++i) {
const { x: x1, y: y1, r } = trace[i - 1],
{ x: x2, y: y2 } = trace[i];
ctx.beginPath();
ctx.moveTo(scaleX(x1), scaleY(y1));
ctx.lineTo(scaleX(x2), scaleY(y2));
ctx.strokeStyle = d3.interpolateWarm(r);
ctx.lineWidth = 2;
ctx.stroke();
if (i === 1 || i === trace.length - 1) {
ctx.beginPath();
ctx.rect(scaleX(x1) - 10, scaleY(y1) - 10, 20, 20);
ctx.strokeStyle = "gray";
ctx.lineWidth = 1;
ctx.stroke();
}
}
}
if (checkboxes.includes("Hessian")) {
for (let i = 1; i < traceNewton.length; ++i) {
const { x: x1, y: y1, r } = traceNewton[i - 1],
{ x: x2, y: y2 } = traceNewton[i];
ctx.beginPath();
ctx.moveTo(scaleX(x1), scaleY(y1));
ctx.lineTo(scaleX(x2), scaleY(y2));
ctx.strokeStyle = d3.interpolateGreys(r);
ctx.lineWidth = 2;
ctx.stroke();
if (i === 1 || i === traceNewton.length - 1) {
ctx.beginPath();
if (i === 1) ctx.rect(scaleX(x1) - 5, scaleY(y1) - 5, 10, 10);
else ctx.rect(scaleX(x2) - 5, scaleY(y2) - 5, 10, 10);
ctx.strokeStyle = "white";
ctx.lineWidth = 2;
ctx.stroke();
}
}
}
}