UNPKG

venny

Version:

Declarative Venn diagrams

57 lines (56 loc) 2.06 kB
// Code adapted from https://github.com/benfred/fmin import { dot, norm2, scale, weightedSum } from './blas1'; import { wolfeLineSearch } from './line-search'; export function conjugateGradient(f, initial, params) { // allocate all memory up front here, keep out of the loop for perfomance // reasons let current = { x: initial.slice(), fx: 0, fxprime: initial.slice() }; let next = { x: initial.slice(), fx: 0, fxprime: initial.slice() }; let temp = undefined; const yk = initial.slice(); let a = 1; params = params || {}; const maxIterations = params.maxIterations || initial.length * 20; current.fx = f(current.x, current.fxprime); const pk = current.fxprime.slice(); scale(pk, current.fxprime, -1); for (let i = 0; i < maxIterations; ++i) { a = wolfeLineSearch(f, pk, current, next, a); // todo: history in wrong spot? if (params.history) { params.history.push({ x: current.x.slice(), fx: current.fx, fxprime: current.fxprime.slice(), alpha: a, }); } if (!a) { // faiiled to find point that satifies wolfe conditions. // reset direction for next iteration scale(pk, current.fxprime, -1); } else { // update direction using Polak–Ribiere CG method weightedSum(yk, 1, next.fxprime, -1, current.fxprime); const delta_k = dot(current.fxprime, current.fxprime); const beta_k = Math.max(0, dot(yk, next.fxprime) / delta_k); weightedSum(pk, beta_k, pk, -1, next.fxprime); temp = current; current = next; next = temp; } if (norm2(current.fxprime) <= 1e-5) { break; } } if (params.history) { params.history.push({ x: current.x.slice(), fx: current.fx, fxprime: current.fxprime.slice(), alpha: a, }); } return current; }