/// <summary> /// Evaluates the Jacobian of a multivariate function f at vector x. /// </summary> /// <remarks> /// This function assumes that the length of vector x consistent with the argument count of f. /// </remarks> /// <param name="f">Multivariate function handle.</param> /// <param name="x">Points at which to evaluate Jacobian.</param> /// <returns>Jacobian vector.</returns> public double[] Evaluate(Func <double[], double> f, double[] x) { var jacobian = new double[x.Length]; for (var i = 0; i < jacobian.Length; i++) { jacobian[i] = _df.EvaluatePartialDerivative(f, x, i, 1); } return(jacobian); }
/// <summary> /// Evaluates the Hessian of a multivariate function f at points x. /// </summary> /// <remarks> /// This method of computing the Hessian is only vaid for Lipschitz continuous functions. /// The function mirrors the Hessian along the diagonal since d2f/dxdy = d2f/dydx for continuously differentiable functions. /// </remarks> /// <param name="f">Multivariate function handle.></param> /// <param name="x">Points at which to evaluate Hessian.></param> /// <returns>Hessian tensor.</returns> public double[,] Evaluate(Func <double[], double> f, double[] x) { var hessian = new double[x.Length, x.Length]; // Compute diagonal elements for (var row = 0; row < x.Length; row++) { hessian[row, row] = _df.EvaluatePartialDerivative(f, x, row, 2); } // Compute non-diagonal elements for (var row = 0; row < x.Length; row++) { for (var col = 0; col < row; col++) { var mixedPartial = _df.EvaluateMixedPartialDerivative(f, x, new[] { row, col }, 2); hessian[row, col] = mixedPartial; hessian[col, row] = mixedPartial; } } return(hessian); }