forked from tsai/mathnet-numerics
committed by
Christoph Ruegg
12 changed files with 502 additions and 24 deletions
@ -1,11 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Text; |
|
||||
|
|
||||
namespace MathNet.Numerics.Optimization |
|
||||
{ |
|
||||
class BFGS |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,131 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.Optimization |
||||
|
{ |
||||
|
public class BfgsMinimizer |
||||
|
{ |
||||
|
public double GradientTolerance { get; set; } |
||||
|
public int MaximumIterations { get; set; } |
||||
|
|
||||
|
public BfgsMinimizer(double gradient_tolerance, int maximum_iterations) |
||||
|
{ |
||||
|
this.GradientTolerance = gradient_tolerance; |
||||
|
this.MaximumIterations = maximum_iterations; |
||||
|
} |
||||
|
|
||||
|
public MinimizationOutput FindMinimum(IObjectiveFunction objective, Vector<double> initial_guess) |
||||
|
{ |
||||
|
if (!objective.GradientSupported) |
||||
|
throw new IncompatibleObjectiveException("Gradient not supported in objective function, but required for BFGS minimization."); |
||||
|
|
||||
|
if (!(objective is ObjectiveChecker)) |
||||
|
objective = new ObjectiveChecker(objective, this.ValidateObjective, this.ValidateGradient, null); |
||||
|
|
||||
|
IEvaluation initial_eval = objective.Evaluate(initial_guess); |
||||
|
|
||||
|
// Check that we're not already done
|
||||
|
if (this.ExitCriteriaSatisfied(initial_guess, initial_eval.Gradient)) |
||||
|
return new MinimizationOutput(initial_eval, 0); |
||||
|
|
||||
|
// Set up line search algorithm
|
||||
|
var line_searcher = new WeakWolfeLineSearch(1e-4, 0.9, 1000); |
||||
|
|
||||
|
// Declare state variables
|
||||
|
IEvaluation candidate_point; |
||||
|
double step_size; |
||||
|
Vector<double> gradient, previous_gradient, step, search_direction; |
||||
|
Matrix<double> inverse_pseudo_hessian; |
||||
|
|
||||
|
// First step
|
||||
|
inverse_pseudo_hessian = Matrix<double>.Build.DiagonalIdentity(initial_guess.Count); |
||||
|
search_direction = -initial_eval.Gradient; |
||||
|
step_size = 100 * this.GradientTolerance / (search_direction * search_direction); |
||||
|
|
||||
|
LineSearchOutput result; |
||||
|
try |
||||
|
{ |
||||
|
result = line_searcher.FindConformingStep(objective, initial_eval, search_direction, step_size); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
throw new InnerOptimizationException("Line search failed.", e); |
||||
|
} |
||||
|
|
||||
|
candidate_point = result.FunctionInfoAtMinimum; |
||||
|
gradient = candidate_point.Gradient; |
||||
|
previous_gradient = initial_eval.Gradient; |
||||
|
step = candidate_point.Point - initial_guess; |
||||
|
step_size = result.FinalStep; |
||||
|
|
||||
|
// Subsequent steps
|
||||
|
int iterations = 1; |
||||
|
int total_line_search_steps = result.Iterations; |
||||
|
int iterations_with_nontrivial_line_search = result.Iterations > 0 ? 0 : 1; |
||||
|
int steepest_descent_resets = 0; |
||||
|
while (!this.ExitCriteriaSatisfied(candidate_point.Point, candidate_point.Gradient) && iterations < this.MaximumIterations) |
||||
|
{ |
||||
|
var y = candidate_point.Gradient - previous_gradient; |
||||
|
|
||||
|
double sy = step * y; |
||||
|
inverse_pseudo_hessian = inverse_pseudo_hessian + ((sy + y * inverse_pseudo_hessian * y) / Math.Pow(sy, 2.0)) * step.OuterProduct(step) - ( (inverse_pseudo_hessian * y.ToColumnMatrix())*step.ToRowMatrix() + step.ToColumnMatrix()*(y.ToRowMatrix() * inverse_pseudo_hessian)) * (1.0 / sy); |
||||
|
|
||||
|
search_direction = -inverse_pseudo_hessian * candidate_point.Gradient; |
||||
|
|
||||
|
if (search_direction * candidate_point.Gradient >= 0) |
||||
|
{ |
||||
|
search_direction = -candidate_point.Gradient; |
||||
|
inverse_pseudo_hessian = Matrix<double>.Build.DiagonalIdentity(initial_guess.Count); |
||||
|
steepest_descent_resets += 1; |
||||
|
} |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
result = line_searcher.FindConformingStep(objective, candidate_point, search_direction, 1.0); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
throw new InnerOptimizationException("Line search failed.", e); |
||||
|
} |
||||
|
|
||||
|
iterations_with_nontrivial_line_search += result.Iterations > 0 ? 1 : 0; |
||||
|
total_line_search_steps += result.Iterations; |
||||
|
|
||||
|
step_size = result.FinalStep; |
||||
|
step = result.FunctionInfoAtMinimum.Point - candidate_point.Point; |
||||
|
previous_gradient = candidate_point.Gradient; |
||||
|
candidate_point = result.FunctionInfoAtMinimum; |
||||
|
|
||||
|
iterations += 1; |
||||
|
} |
||||
|
|
||||
|
if (iterations == this.MaximumIterations) |
||||
|
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", this.MaximumIterations)); |
||||
|
|
||||
|
return new MinimizationWithLineSearchOutput(candidate_point, iterations, total_line_search_steps, iterations_with_nontrivial_line_search); |
||||
|
} |
||||
|
|
||||
|
private bool ExitCriteriaSatisfied(Vector<double> candidate_point, Vector<double> gradient) |
||||
|
{ |
||||
|
return gradient.Norm(2.0) < this.GradientTolerance; |
||||
|
} |
||||
|
|
||||
|
private void ValidateGradient(Vector<double> gradient, Vector<double> input) |
||||
|
{ |
||||
|
foreach (var x in gradient) |
||||
|
{ |
||||
|
if (Double.IsNaN(x) || Double.IsInfinity(x)) |
||||
|
throw new EvaluationException("Non-finite gradient returned."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void ValidateObjective(double objective, Vector<double> input) |
||||
|
{ |
||||
|
if (Double.IsNaN(objective) || Double.IsInfinity(objective)) |
||||
|
throw new EvaluationException("Non-finite objective function returned."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,128 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
using LU = MathNet.Numerics.LinearAlgebra.Factorization.LU<double>; |
||||
|
|
||||
|
namespace MathNet.Numerics.Optimization |
||||
|
{ |
||||
|
public class NewtonMinimizer |
||||
|
{ |
||||
|
public double GradientTolerance { get; set; } |
||||
|
public int MaximumIterations { get; set; } |
||||
|
public bool UseLineSearch { get; set; } |
||||
|
|
||||
|
public NewtonMinimizer(double gradient_tolerance, int maximum_iterations, bool use_line_search=false) |
||||
|
{ |
||||
|
this.GradientTolerance = gradient_tolerance; |
||||
|
this.MaximumIterations = maximum_iterations; |
||||
|
this.UseLineSearch = use_line_search; |
||||
|
} |
||||
|
|
||||
|
public MinimizationOutput FindMinimum(IObjectiveFunction objective, Vector<double> initial_guess) |
||||
|
{ |
||||
|
if (!objective.GradientSupported) |
||||
|
throw new IncompatibleObjectiveException("Gradient not supported in objective function, but required for Newton minimization."); |
||||
|
|
||||
|
if (!objective.HessianSupported) |
||||
|
throw new IncompatibleObjectiveException("Hessian not supported in objective function, but required for Newton minimization."); |
||||
|
|
||||
|
if (!(objective is ObjectiveChecker)) |
||||
|
objective = new ObjectiveChecker(objective, this.ValidateObjective, this.ValidateGradient, this.ValidateHessian); |
||||
|
|
||||
|
IEvaluation initial_eval = objective.Evaluate(initial_guess); |
||||
|
|
||||
|
// Check that we're not already done
|
||||
|
if (this.ExitCriteriaSatisfied(initial_guess, initial_eval.Gradient)) |
||||
|
return new MinimizationOutput(initial_eval, 0); |
||||
|
|
||||
|
// Set up line search algorithm
|
||||
|
var line_searcher = new WeakWolfeLineSearch(1e-4, 0.9, 1000); |
||||
|
|
||||
|
// Declare state variables
|
||||
|
IEvaluation candidate_point = initial_eval; |
||||
|
Vector<double> search_direction; |
||||
|
LineSearchOutput result; |
||||
|
|
||||
|
// Subsequent steps
|
||||
|
int iterations = 0; |
||||
|
int total_line_search_steps = 0; |
||||
|
int iterations_with_nontrivial_line_search = 0; |
||||
|
int steepest_descent_resets = 0; |
||||
|
bool tmp_line_search = false; |
||||
|
while (!this.ExitCriteriaSatisfied(candidate_point.Point, candidate_point.Gradient) && iterations < this.MaximumIterations) |
||||
|
{ |
||||
|
|
||||
|
search_direction = candidate_point.Hessian.LU().Solve(-candidate_point.Gradient); |
||||
|
|
||||
|
if (search_direction * candidate_point.Gradient >= 0) |
||||
|
{ |
||||
|
search_direction = -candidate_point.Gradient; |
||||
|
steepest_descent_resets += 1; |
||||
|
tmp_line_search = true; |
||||
|
} |
||||
|
|
||||
|
if (this.UseLineSearch || tmp_line_search) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
result = line_searcher.FindConformingStep(objective, candidate_point, search_direction, 1.0); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
throw new InnerOptimizationException("Line search failed.", e); |
||||
|
} |
||||
|
iterations_with_nontrivial_line_search += result.Iterations > 0 ? 1 : 0; |
||||
|
total_line_search_steps += result.Iterations; |
||||
|
candidate_point = result.FunctionInfoAtMinimum; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
candidate_point = objective.Evaluate(candidate_point.Point + search_direction); |
||||
|
} |
||||
|
|
||||
|
tmp_line_search = false; |
||||
|
|
||||
|
iterations += 1; |
||||
|
} |
||||
|
|
||||
|
if (iterations == this.MaximumIterations) |
||||
|
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", this.MaximumIterations)); |
||||
|
|
||||
|
return new MinimizationWithLineSearchOutput(candidate_point, iterations, total_line_search_steps, iterations_with_nontrivial_line_search); |
||||
|
} |
||||
|
|
||||
|
private bool ExitCriteriaSatisfied(Vector<double> candidate_point, Vector<double> gradient) |
||||
|
{ |
||||
|
return gradient.Norm(2.0) < this.GradientTolerance; |
||||
|
} |
||||
|
|
||||
|
private void ValidateGradient(Vector<double> gradient, Vector<double> input) |
||||
|
{ |
||||
|
foreach (var x in gradient) |
||||
|
{ |
||||
|
if (Double.IsNaN(x) || Double.IsInfinity(x)) |
||||
|
throw new EvaluationException("Non-finite gradient returned."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void ValidateObjective(double objective, Vector<double> input) |
||||
|
{ |
||||
|
if (Double.IsNaN(objective) || Double.IsInfinity(objective)) |
||||
|
throw new EvaluationException("Non-finite objective function returned."); |
||||
|
} |
||||
|
|
||||
|
private void ValidateHessian(Matrix<double> hessian, Vector<double> input) |
||||
|
{ |
||||
|
for (int ii = 0; ii < hessian.RowCount; ++ii) |
||||
|
{ |
||||
|
for (int jj = 0; jj < hessian.ColumnCount; ++jj) |
||||
|
{ |
||||
|
if (Double.IsNaN(hessian[ii,jj]) || Double.IsInfinity(hessian[ii,jj])) |
||||
|
throw new EvaluationException("Non-finite Hessian returned."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
|
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
using MathNet.Numerics.Optimization; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests |
||||
|
{ |
||||
|
[TestFixture] |
||||
|
public class TestBfgsMinimizer |
||||
|
{ |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Rosenbrock_Easy() |
||||
|
{ |
||||
|
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient); |
||||
|
var solver = new BfgsMinimizer(1e-5, 1000); |
||||
|
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { 1.2, 1.2 })); |
||||
|
|
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Rosenbrock_Hard() |
||||
|
{ |
||||
|
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient); |
||||
|
var solver = new BfgsMinimizer(1e-5, 1000); |
||||
|
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -1.2, 1.0 })); |
||||
|
|
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Rosenbrock_Overton() |
||||
|
{ |
||||
|
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient); |
||||
|
var solver = new BfgsMinimizer(1e-5, 1000); |
||||
|
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -0.9, -0.5 })); |
||||
|
|
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,82 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
|
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
using MathNet.Numerics.Optimization; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests |
||||
|
{ |
||||
|
[TestFixture] |
||||
|
public class TestNewtonMinimizer |
||||
|
{ |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Rosenbrock_Easy() |
||||
|
{ |
||||
|
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient, RosenbrockFunction.Hessian); |
||||
|
var solver = new NewtonMinimizer(1e-5, 1000); |
||||
|
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { 1.2, 1.2 })); |
||||
|
|
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Rosenbrock_Hard() |
||||
|
{ |
||||
|
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient, RosenbrockFunction.Hessian); |
||||
|
var solver = new NewtonMinimizer(1e-5, 1000); |
||||
|
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -1.2, 1.0 })); |
||||
|
|
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Rosenbrock_Overton() |
||||
|
{ |
||||
|
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient, RosenbrockFunction.Hessian); |
||||
|
var solver = new NewtonMinimizer(1e-5, 1000); |
||||
|
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -0.9, -0.5 })); |
||||
|
|
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Linesearch_Rosenbrock_Easy() |
||||
|
{ |
||||
|
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient, RosenbrockFunction.Hessian); |
||||
|
var solver = new NewtonMinimizer(1e-5, 1000, true); |
||||
|
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { 1.2, 1.2 })); |
||||
|
|
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Linesearch_Rosenbrock_Hard() |
||||
|
{ |
||||
|
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient, RosenbrockFunction.Hessian); |
||||
|
var solver = new NewtonMinimizer(1e-5, 1000, true); |
||||
|
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -1.2, 1.0 })); |
||||
|
|
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Linesearch_Rosenbrock_Overton() |
||||
|
{ |
||||
|
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient, RosenbrockFunction.Hessian); |
||||
|
var solver = new NewtonMinimizer(1e-5, 1000, true); |
||||
|
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -0.9, -0.5 })); |
||||
|
|
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using NUnit.Framework; |
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests |
||||
|
{ |
||||
|
[TestFixture] |
||||
|
class TestRosenbrockFunction |
||||
|
{ |
||||
|
[Test] |
||||
|
public void TestGradient() |
||||
|
{ |
||||
|
var input = new LinearAlgebra.Double.DenseVector(new double[]{ -0.9, -0.5 } ); |
||||
|
|
||||
|
var v1 = RosenbrockFunction.Value(input); |
||||
|
var g = RosenbrockFunction.Gradient(input); |
||||
|
|
||||
|
var eps = 1e-5; |
||||
|
var eps0 = (new LinearAlgebra.Double.DenseVector(new double[] { 1.0, 0.0 })) * eps; |
||||
|
var eps1 = (new LinearAlgebra.Double.DenseVector(new double[] { 0.0, 1.0 })) * eps; |
||||
|
|
||||
|
var g0 = (RosenbrockFunction.Value(input + eps0) - RosenbrockFunction.Value(input - eps0)) / (2 * eps); |
||||
|
var g1 = (RosenbrockFunction.Value(input + eps1) - RosenbrockFunction.Value(input - eps1)) / (2 * eps); |
||||
|
|
||||
|
Assert.That(Math.Abs(g0 - g[0]) < 1e-3); |
||||
|
Assert.That(Math.Abs(g1 - g[1]) < 1e-3); |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void TestHessian() |
||||
|
{ |
||||
|
var input = new LinearAlgebra.Double.DenseVector(new double[] { -0.9, -0.5 }); |
||||
|
|
||||
|
var v1 = RosenbrockFunction.Value(input); |
||||
|
var h = RosenbrockFunction.Hessian(input); |
||||
|
|
||||
|
var eps = 1e-5; |
||||
|
|
||||
|
var eps0 = (new LinearAlgebra.Double.DenseVector(new double[] { 1.0, 0.0 })) * eps; |
||||
|
var eps1 = (new LinearAlgebra.Double.DenseVector(new double[] { 0.0, 1.0 })) * eps; |
||||
|
|
||||
|
var epsuu = (new LinearAlgebra.Double.DenseVector(new double[] { 1.0, 1.0 })) * eps; |
||||
|
var epsud = (new LinearAlgebra.Double.DenseVector(new double[] { 1.0, -1.0 })) * eps; |
||||
|
|
||||
|
|
||||
|
|
||||
|
var h00 = (RosenbrockFunction.Value(input + eps0) - 2*RosenbrockFunction.Value(input) + RosenbrockFunction.Value(input - eps0)) / (eps*eps); |
||||
|
var h11 = (RosenbrockFunction.Value(input + eps1) - 2 * RosenbrockFunction.Value(input) + RosenbrockFunction.Value(input - eps1)) / (eps * eps); |
||||
|
var h01 = (RosenbrockFunction.Value(input + epsuu) - RosenbrockFunction.Value(input + epsud) - RosenbrockFunction.Value(input - epsud) + RosenbrockFunction.Value(input - epsuu)) / (4*eps * eps); |
||||
|
|
||||
|
|
||||
|
Assert.That(Math.Abs(h00 - h[0,0]) < 1e-3); |
||||
|
Assert.That(Math.Abs(h11 - h[1,1]) < 1e-3); |
||||
|
Assert.That(Math.Abs(h01 - h[0, 1]) < 1e-3); |
||||
|
Assert.That(Math.Abs(h01 - h[1, 0]) < 1e-3); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue