backtrack = function(f,xNow,t,alpha) {
let nDim = xNow.length;
let fNow = f(xNow);
let dt = t/1000.;
const dfdx = [];
let dfmag = 0;
for (let n=0; n<nDim; n++) {
let xPlusDt = [...xNow];
xPlusDt[n] += dt;
let xMinusDt = [...xNow];
xMinusDt[n] -= dt;
let dfdxn = ( f(xPlusDt)-f(xMinusDt) )/(2*dt);
dfdx.push(dfdxn);
dfmag += dfdxn**2;
}
dfmag = Math.sqrt(dfmag);
const dfdxNorm = dfdx.map( d => d/dfmag );
let xNew = xNow.map( (d,idx) => (d - t*dfdxNorm[idx]) );
let fNew = f(xNew);
let dotProd = 0.;
dfdx.forEach( (d,idx) => dotProd += d*dfdxNorm[idx] );
let dist = dotProd*alpha*t;
while (fNow - fNew - dist < 0) {
t *= 0.8;
xNew = xNow.map( (d,idx) => (d - t*dfdxNorm[idx]) );
fNew = f(xNew);
dist = dotProd*alpha*t;
}
return ({x:xNew,f:fNew,t});
}