diff --git a/src/Numerics.Tests/OptimizationTests/NonLinearCurveFittingTests.cs b/src/Numerics.Tests/OptimizationTests/NonLinearCurveFittingTests.cs
index cdaad350f..ab3cb4d44 100644
--- a/src/Numerics.Tests/OptimizationTests/NonLinearCurveFittingTests.cs
+++ b/src/Numerics.Tests/OptimizationTests/NonLinearCurveFittingTests.cs
@@ -201,6 +201,20 @@ public void Rat43_TRNCG_Dif()
}
}
+ [Test]
+ public void Rat43_TREXACT_Dif()
+ {
+ var obj = ObjectiveFunction.NonlinearModel(Rat43Model, Rat43X, Rat43Y, accuracyOrder: 6);
+ var solver = new TrustRegionExactMinimizer();
+ var result = solver.FindMinimum(obj, Rat43Start2);
+
+ for (var i = 0; i < result.MinimizingPoint.Count; i++)
+ {
+ AssertHelpers.AlmostEqualRelative(Rat43Pbest[i], result.MinimizingPoint[i], 2);
+ AssertHelpers.AlmostEqualRelative(Rat43Pstd[i], result.StandardErrors[i], 2);
+ }
+ }
+
[Test]
public void Rat43_Bfgs_Dif()
{
@@ -411,6 +425,20 @@ public void BoxBod_TRNCG_Dif()
}
}
+ [Test]
+ public void BoxBod_TREXACT_Dif()
+ {
+ var obj = ObjectiveFunction.NonlinearModel(BoxBodModel, BoxBodX, BoxBodY, accuracyOrder: 6);
+ var solver = new TrustRegionExactMinimizer();
+ var result = solver.FindMinimum(obj, BoxBodStart2);
+
+ for (var i = 0; i < result.MinimizingPoint.Count; i++)
+ {
+ AssertHelpers.AlmostEqualRelative(BoxBodPbest[i], result.MinimizingPoint[i], 3);
+ AssertHelpers.AlmostEqualRelative(BoxBodPstd[i], result.StandardErrors[i], 3);
+ }
+ }
+
[Test]
public void BoxBod_Bfgs_Der()
{
@@ -581,6 +609,20 @@ public void Thurber_TRNCG_Dif()
}
}
+ [Test]
+ public void Thurber_TREXACT_Dif()
+ {
+ var obj = ObjectiveFunction.NonlinearModel(ThurberModel, ThurberX, ThurberY, accuracyOrder: 6);
+ var solver = new TrustRegionExactMinimizer();
+ var result = solver.FindMinimum(obj, ThurberStart, scales: ThurberScales);
+
+ for (var i = 0; i < result.MinimizingPoint.Count; i++)
+ {
+ AssertHelpers.AlmostEqualRelative(ThurberPbest[i], result.MinimizingPoint[i], 3);
+ AssertHelpers.AlmostEqualRelative(ThurberPstd[i], result.StandardErrors[i], 3);
+ }
+ }
+
[Test]
public void Thurber_Bfgs_Dif()
{
diff --git a/src/Numerics/Optimization/TrustRegion/ITrustRegionSubProblem.cs b/src/Numerics/Optimization/TrustRegion/ITrustRegionSubProblem.cs
index 151913378..861d7b86f 100644
--- a/src/Numerics/Optimization/TrustRegion/ITrustRegionSubProblem.cs
+++ b/src/Numerics/Optimization/TrustRegion/ITrustRegionSubProblem.cs
@@ -2,11 +2,29 @@
namespace MathNet.Numerics.Optimization.TrustRegion
{
+ ///
+ /// Defines the interface for solving a trust region subproblem in nonlinear least squares minimization.
+ /// This interface provides properties to retrieve the computed step and a flag indicating whether the solution hit the trust region boundary,
+ /// as well as a method to solve the subproblem given an objective model and a trust region radius.
+ ///
public interface ITrustRegionSubproblem
{
+ ///
+ /// Gets the computed parameter step vector after solving the subproblem.
+ ///
Vector Pstep { get; }
+
+ ///
+ /// Gets a value indicating whether the solution of the subproblem hit the trust region boundary.
+ ///
bool HitBoundary { get; }
- void Solve(IObjectiveModel objective, double radius);
+ ///
+ /// Solves the trust region subproblem using the provided gradient and Hessian.
+ ///
+ /// The scaled gradient vector
+ /// The scaled Hessian matrix
+ /// Trust region radius
+ void Solve(Vector gradient, Matrix hessian, double delta);
}
}
diff --git a/src/Numerics/Optimization/TrustRegion/Subproblems/DogLegSubproblem.cs b/src/Numerics/Optimization/TrustRegion/Subproblems/DogLegSubproblem.cs
index e01b689bf..822c18dba 100644
--- a/src/Numerics/Optimization/TrustRegion/Subproblems/DogLegSubproblem.cs
+++ b/src/Numerics/Optimization/TrustRegion/Subproblems/DogLegSubproblem.cs
@@ -2,23 +2,32 @@
namespace MathNet.Numerics.Optimization.TrustRegion.Subproblems
{
+ ///
+ /// Implements the Dog-Leg method for solving trust region subproblems.
+ ///
+ ///
+ /// The Dog-Leg method combines the Gauss-Newton step and the steepest descent step
+ /// to find an approximate solution to the trust region subproblem. It provides a good
+ /// compromise between the computational efficiency of steepest descent and the fast
+ /// convergence of Gauss-Newton near the solution.
+ ///
internal class DogLegSubproblem : ITrustRegionSubproblem
{
+ ///
public Vector Pstep { get; private set; }
+ ///
public bool HitBoundary { get; private set; }
- public void Solve(IObjectiveModel objective, double delta)
+ ///
+ public void Solve(Vector gradient, Matrix hessian, double delta)
{
- var Gradient = objective.Gradient;
- var Hessian = objective.Hessian;
-
// newton point, the Gauss–Newton step by solving the normal equations
- var Pgn = -Hessian.PseudoInverse() * Gradient; // Hessian.Solve(Gradient) fails so many times...
+ var Pgn = -hessian.PseudoInverse() * gradient; // hessian.Solve(gradient) fails so many times...
// cauchy point, steepest descent direction is given by
- var alpha = Gradient.DotProduct(Gradient) / (Hessian * Gradient).DotProduct(Gradient);
- var Psd = -alpha * Gradient;
+ var alpha = gradient.DotProduct(gradient) / (hessian * gradient).DotProduct(gradient);
+ var Psd = -alpha * gradient;
// update step and prectted reduction
if (Pgn.L2Norm() <= delta)
diff --git a/src/Numerics/Optimization/TrustRegion/Subproblems/ExactSubproblem.cs b/src/Numerics/Optimization/TrustRegion/Subproblems/ExactSubproblem.cs
new file mode 100644
index 000000000..c97b8851a
--- /dev/null
+++ b/src/Numerics/Optimization/TrustRegion/Subproblems/ExactSubproblem.cs
@@ -0,0 +1,235 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// https://numerics.mathdotnet.com
+// https://github.com/mathnet/mathnet-numerics
+//
+// Copyright (c) 2009-$CURRENT_YEAR$ Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using MathNet.Numerics.LinearAlgebra;
+using System;
+using System.Linq;
+
+namespace MathNet.Numerics.Optimization.TrustRegion.Subproblems
+{
+ ///
+ /// Implements the Exact method for solving trust region subproblems.
+ ///
+ ///
+ /// The Exact method uses eigenvalue decomposition to find the exact solution to the trust region subproblem.
+ /// It is more computationally expensive than other methods but can provide more accurate solutions,
+ /// especially when the Hessian is indefinite or when high accuracy is required.
+ ///
+ internal class ExactSubproblem : ITrustRegionSubproblem
+ {
+ ///
+ public Vector Pstep { get; private set; }
+
+ ///
+ public bool HitBoundary { get; private set; }
+
+ ///
+ public void Solve(Vector gradient, Matrix hessian, double delta)
+ {
+ // Get the dimension of the problem
+ var n = gradient.Count;
+
+ try
+ {
+ // Perform eigenvalue decomposition of the Hessian
+ var evd = hessian.Evd();
+ var Q = evd.EigenVectors;
+ var eigvals = evd.EigenValues.Real();
+
+ // Transform the gradient to the eigenvector basis
+ var gHat = Q.Transpose() * gradient;
+
+ // Try the interior solution first
+ var isInteriorValid = true;
+ var pInterior = Vector.Build.Dense(n);
+
+ // Tolerance for numerical stability
+ const double epsilon = 1e-12;
+
+ for (var i = 0; i < n; i++)
+ {
+ if (Math.Abs(eigvals[i]) < epsilon)
+ {
+ // Handle zero eigenvalues
+ if (Math.Abs(gHat[i]) > epsilon)
+ {
+ // If gHat[i] != 0 when λ_i = 0, Newton step goes to infinity
+ isInteriorValid = false;
+ break;
+ }
+ pInterior[i] = 0;
+ }
+ else if (eigvals[i] < 0)
+ {
+ // Negative eigenvalue implies the Hessian is not positive definite
+ isInteriorValid = false;
+ break;
+ }
+ else
+ {
+ // Compute the Newton step component
+ pInterior[i] = -gHat[i] / eigvals[i];
+ }
+ }
+
+ if (isInteriorValid)
+ {
+ // Transform back to original coordinates
+ var p = Q * pInterior;
+
+ // Check if the solution is within the trust region
+ if (p.L2Norm() <= delta)
+ {
+ Pstep = p;
+ HitBoundary = false;
+ return;
+ }
+ }
+
+ // If the Newton step is outside the trust region or invalid,
+ // solve the constrained problem with the solution on the boundary
+
+ // Find the optimal Lagrange multiplier lambda using a root-finding approach
+ var lambda = FindOptimalLambda(eigvals, gHat, delta);
+
+ // Compute the solution with this lambda
+ var pBoundary = Vector.Build.Dense(n);
+ for (var i = 0; i < n; i++)
+ {
+ var denominator = eigvals[i] + lambda;
+ if (Math.Abs(denominator) < epsilon)
+ {
+ // Handle potential division by near-zero
+ pBoundary[i] = gHat[i] > 0 ? -delta : delta;
+ }
+ else
+ {
+ pBoundary[i] = -gHat[i] / denominator;
+ }
+ }
+
+ // Transform back to original coordinates
+ Pstep = Q * pBoundary;
+ HitBoundary = true;
+ }
+ catch (Exception)
+ {
+ // Fallback to a more robust method if eigenvalue decomposition fails
+ // For example, use a steepest descent step
+ var alpha = gradient.DotProduct(gradient) / (hessian * gradient).DotProduct(gradient);
+ Pstep = -Math.Min(alpha, delta / gradient.L2Norm()) * gradient;
+ HitBoundary = alpha * gradient.L2Norm() >= delta;
+ }
+ }
+
+ ///
+ /// Finds the optimal Lagrange multiplier to ensure the solution lies on the trust region boundary.
+ ///
+ /// Eigenvalues of the Hessian
+ /// Gradient in the eigenvector basis
+ /// Trust region radius
+ /// The optimal Lagrange multiplier
+ private static double FindOptimalLambda(Vector eigvals, Vector gHat, double delta)
+ {
+ // Tolerance for numerical stability
+ const double epsilon = 1e-12;
+ const int maxIterations = 100;
+ const double tolerance = 1e-10;
+
+ // Function to evaluate the norm of the solution for a given lambda
+ double PhiFunction(double lambda)
+ {
+ var sum = 0.0;
+ for (var i = 0; i < eigvals.Count; i++)
+ {
+ var denominator = eigvals[i] + lambda;
+ if (Math.Abs(denominator) > epsilon)
+ {
+ var term = gHat[i] / denominator;
+ sum += term * term;
+ }
+ else if (Math.Abs(gHat[i]) > epsilon)
+ {
+ // If denominator is near zero but gHat[i] is not,
+ // this would result in a very large term
+ return double.PositiveInfinity;
+ }
+ }
+ return Math.Sqrt(sum) - delta;
+ }
+
+ // Find the minimum eigenvalue to establish a lower bound for lambda
+ var lambdaMin = -eigvals.Min();
+
+ // Start with lambdaMin plus a small value to ensure positive definiteness
+ var lambdaLower = Math.Max(0.0, lambdaMin + epsilon);
+ var lambdaUpper = lambdaLower + 1.0;
+
+ // Expand the upper bound until phi(lambdaUpper) < 0
+ var expandCount = 0;
+ while (PhiFunction(lambdaUpper) > 0 && expandCount < 30)
+ {
+ lambdaLower = lambdaUpper;
+ lambdaUpper *= 10;
+ expandCount++;
+ }
+
+ if (expandCount >= 30)
+ {
+ // If we can't find a suitable upper bound, use a fallback value
+ return lambdaUpper;
+ }
+
+ // Use bisection method to find the root of the phi function
+ var lambdaMid = 0.0;
+ double phiMid;
+ for (var i = 0; i < maxIterations; i++)
+ {
+ lambdaMid = (lambdaLower + lambdaUpper) / 2.0;
+ phiMid = PhiFunction(lambdaMid);
+
+ if (Math.Abs(phiMid) < tolerance)
+ {
+ break;
+ }
+
+ if (phiMid > 0)
+ {
+ lambdaLower = lambdaMid;
+ }
+ else
+ {
+ lambdaUpper = lambdaMid;
+ }
+ }
+
+ return lambdaMid;
+ }
+ }
+}
diff --git a/src/Numerics/Optimization/TrustRegion/Subproblems/NewtonCGSubproblem.cs b/src/Numerics/Optimization/TrustRegion/Subproblems/NewtonCGSubproblem.cs
index acbf83ce3..8e3a2aece 100644
--- a/src/Numerics/Optimization/TrustRegion/Subproblems/NewtonCGSubproblem.cs
+++ b/src/Numerics/Optimization/TrustRegion/Subproblems/NewtonCGSubproblem.cs
@@ -3,35 +3,54 @@
namespace MathNet.Numerics.Optimization.TrustRegion.Subproblems
{
+ ///
+ /// Implements the Newton Conjugate Gradient method for solving trust region subproblems.
+ ///
+ ///
+ /// The Newton-CG method iteratively improves the solution using conjugate gradient iterations
+ /// while ensuring the solution stays within the trust region boundary. This method is
+ /// particularly effective for large-scale problems and can handle cases where the Hessian
+ /// is indefinite by detecting directions of negative curvature.
+ ///
internal class NewtonCGSubproblem : ITrustRegionSubproblem
{
+ ///
public Vector Pstep { get; private set; }
+ ///
public bool HitBoundary { get; private set; }
- public void Solve(IObjectiveModel objective, double delta)
+ ///
+ public void Solve(Vector gradient, Matrix hessian, double delta)
{
- var Gradient = objective.Gradient;
- var Hessian = objective.Hessian;
-
// define tolerance
- var gnorm = Gradient.L2Norm();
+ var gnorm = gradient.L2Norm();
var tolerance = Math.Min(0.5, Math.Sqrt(gnorm)) * gnorm;
// initialize internal variables
- var z = Vector.Build.Dense(Hessian.RowCount);
- var r = Gradient;
+ var z = Vector.Build.Dense(hessian.RowCount);
+ var r = gradient;
var d = -r;
while (true)
{
- var Bd = Hessian * d;
+ var Bd = hessian * d;
var dBd = d.DotProduct(Bd);
if (dBd <= 0)
{
+ // Direction of negative curvature found
+ // Calculate two boundary points and choose the one with lower model value
var t = Util.FindBeta(1, z, d, delta);
- Pstep = z + t.Item1 * d;
+ var pa = z + t.Item1 * d;
+ var pb = z + t.Item2 * d;
+
+ // Evaluate quadratic model at both points
+ var valueA = Util.CalculateQuadraticModel(gradient, hessian, pa);
+ var valueB = Util.CalculateQuadraticModel(gradient, hessian, pb);
+
+ // Choose the point with the lower model value
+ Pstep = valueA < valueB ? pa : pb;
HitBoundary = true;
return;
}
@@ -39,7 +58,7 @@ public void Solve(IObjectiveModel objective, double delta)
var r_sq = r.DotProduct(r);
var alpha = r_sq / dBd;
var znext = z + alpha * d;
- if(znext.L2Norm() >= delta)
+ if (znext.L2Norm() >= delta)
{
var t = Util.FindBeta(1, z, d, delta);
Pstep = z + t.Item2 * d;
diff --git a/src/Numerics/Optimization/TrustRegion/Subproblems/Util.cs b/src/Numerics/Optimization/TrustRegion/Subproblems/Util.cs
index 23444f67a..233b57f26 100644
--- a/src/Numerics/Optimization/TrustRegion/Subproblems/Util.cs
+++ b/src/Numerics/Optimization/TrustRegion/Subproblems/Util.cs
@@ -5,6 +5,14 @@ namespace MathNet.Numerics.Optimization.TrustRegion.Subproblems
{
internal static class Util
{
+ ///
+ /// Finds the two intersection points of a line with the trust region boundary.
+ ///
+ /// Scaling factor for steepest descent direction
+ /// Steepest descent direction vector
+ /// Gauss-Newton direction vector
+ /// Trust region radius
+ /// A tuple containing two beta values, sorted from low to high
public static (double, double) FindBeta(double alpha, Vector sd, Vector gn, double delta)
{
// Pstep is intersection of the trust region boundary
@@ -29,5 +37,24 @@ public static (double, double) FindBeta(double alpha, Vector sd, Vector<
// return sorted beta
return beta1 < beta2 ? (beta1, beta2) : (beta2, beta1);
}
+
+ ///
+ /// Calculates the value of the quadratic model at a given point.
+ /// The quadratic model is defined as:
+ /// m(p) = g^T * p + 0.5 * p^T * H * p
+ /// where g is the gradient and H is the Hessian at the current point.
+ ///
+ /// The gradient vector
+ /// The Hessian matrix
+ /// The point at which to evaluate the quadratic model
+ /// The value of the quadratic model at point p
+ public static double CalculateQuadraticModel(Vector gradient, Matrix hessian, Vector p)
+ {
+ // Quadratic model: m(p) = g^T * p + 0.5 * p^T * H * p
+ var linearTerm = gradient.DotProduct(p);
+ var quadraticTerm = 0.5 * p.DotProduct(hessian * p);
+
+ return linearTerm + quadraticTerm;
+ }
}
}
diff --git a/src/Numerics/Optimization/TrustRegion/TrustRegionDogLegMinimizer.cs b/src/Numerics/Optimization/TrustRegion/TrustRegionDogLegMinimizer.cs
index c07fffaab..dd7c5c942 100644
--- a/src/Numerics/Optimization/TrustRegion/TrustRegionDogLegMinimizer.cs
+++ b/src/Numerics/Optimization/TrustRegion/TrustRegionDogLegMinimizer.cs
@@ -1,10 +1,19 @@
namespace MathNet.Numerics.Optimization.TrustRegion
{
+ ///
+ /// Implements nonlinear least squares fitting using the trust region dogleg algorithm.
+ /// This class inherits from .
+ ///
public sealed class TrustRegionDogLegMinimizer : TrustRegionMinimizerBase
{
///
- /// Non-linear least square fitting by the trust region dogleg algorithm.
+ /// Initializes a new instance of the class using the trust region dogleg algorithm.
///
+ /// The tolerance for the infinity norm of the gradient. Default is 1E-8.
+ /// The tolerance for the parameter update step size. Default is 1E-8.
+ /// The tolerance for the function value (residual sum of squares). Default is 1E-8.
+ /// The tolerance for the trust region radius. Default is 1E-8.
+ /// The maximum number of iterations. Default is -1 (unlimited).
public TrustRegionDogLegMinimizer(double gradientTolerance = 1E-8, double stepTolerance = 1E-8, double functionTolerance = 1E-8, double radiusTolerance = 1E-8, int maximumIterations = -1)
: base(TrustRegionSubproblem.DogLeg(), gradientTolerance, stepTolerance, functionTolerance, radiusTolerance, maximumIterations)
{ }
diff --git a/src/Numerics/Optimization/TrustRegion/TrustRegionExactMinimizer.cs b/src/Numerics/Optimization/TrustRegion/TrustRegionExactMinimizer.cs
new file mode 100644
index 000000000..85bd8ae37
--- /dev/null
+++ b/src/Numerics/Optimization/TrustRegion/TrustRegionExactMinimizer.cs
@@ -0,0 +1,54 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// https://numerics.mathdotnet.com
+// https://github.com/mathnet/mathnet-numerics
+//
+// Copyright (c) 2009-$CURRENT_YEAR$ Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.Optimization.TrustRegion
+{
+ ///
+ /// Implements a trust region minimizer using the Exact subproblem solver with eigenvalue decomposition.
+ ///
+ ///
+ /// The Exact method provides the most accurate solution to the trust region subproblem but is more
+ /// computationally expensive. It's particularly useful when high accuracy is required or when
+ /// the Hessian has negative eigenvalues.
+ ///
+ public sealed class TrustRegionExactMinimizer : TrustRegionMinimizerBase
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The gradient tolerance used to determine convergence.
+ /// The step size tolerance used to determine convergence.
+ /// The function value tolerance used to determine convergence.
+ /// The trust region radius tolerance used to determine convergence.
+ /// The maximum number of iterations. -1 means no limit.
+ public TrustRegionExactMinimizer(double gradientTolerance = 1E-8, double stepTolerance = 1E-8, double functionTolerance = 1E-8, double radiusTolerance = 1E-8, int maximumIterations = -1)
+ : base(TrustRegionSubproblem.Exact(), gradientTolerance, stepTolerance, functionTolerance, radiusTolerance, maximumIterations)
+ { }
+ }
+}
diff --git a/src/Numerics/Optimization/TrustRegion/TrustRegionMinimizerBase.cs b/src/Numerics/Optimization/TrustRegion/TrustRegionMinimizerBase.cs
index 222b3ccf3..397da4f1e 100644
--- a/src/Numerics/Optimization/TrustRegion/TrustRegionMinimizerBase.cs
+++ b/src/Numerics/Optimization/TrustRegion/TrustRegionMinimizerBase.cs
@@ -161,7 +161,7 @@ public NonlinearMinimizationResult Minimum(ITrustRegionSubproblem subproblem, IO
iterations++;
// solve the subproblem
- subproblem.Solve(objective, delta);
+ subproblem.Solve(Gradient, Hessian, delta);
Pstep = subproblem.Pstep;
hitBoundary = subproblem.HitBoundary;
diff --git a/src/Numerics/Optimization/TrustRegion/TrustRegionNewtonCGMinimizer.cs b/src/Numerics/Optimization/TrustRegion/TrustRegionNewtonCGMinimizer.cs
index faee55487..4c754981f 100644
--- a/src/Numerics/Optimization/TrustRegion/TrustRegionNewtonCGMinimizer.cs
+++ b/src/Numerics/Optimization/TrustRegion/TrustRegionNewtonCGMinimizer.cs
@@ -1,10 +1,19 @@
namespace MathNet.Numerics.Optimization.TrustRegion
{
+ ///
+ /// Implements nonlinear least squares fitting using the trust region Newton-Conjugate-Gradient algorithm.
+ /// This class inherits from .
+ ///
public sealed class TrustRegionNewtonCGMinimizer : TrustRegionMinimizerBase
{
///
- /// Non-linear least square fitting by the trust region Newton-Conjugate-Gradient algorithm.
+ /// Initializes a new instance of the class using the trust region Newton-Conjugate-Gradient algorithm.
///
+ /// The tolerance for the infinity norm of the gradient. Default is 1E-8.
+ /// The tolerance for the parameter update step size. Default is 1E-8.
+ /// The tolerance for the function value (residual sum of squares). Default is 1E-8.
+ /// The tolerance for the trust region radius. Default is 1E-8.
+ /// The maximum number of iterations. Default is -1 (unlimited).
public TrustRegionNewtonCGMinimizer(double gradientTolerance = 1E-8, double stepTolerance = 1E-8, double functionTolerance = 1E-8, double radiusTolerance = 1E-8, int maximumIterations = -1)
: base(TrustRegionSubproblem.NewtonCG(), gradientTolerance, stepTolerance, functionTolerance, radiusTolerance, maximumIterations)
{ }
diff --git a/src/Numerics/Optimization/TrustRegion/TrustRegionSubProblem.cs b/src/Numerics/Optimization/TrustRegion/TrustRegionSubProblem.cs
index 15055a8af..3c280e2a1 100644
--- a/src/Numerics/Optimization/TrustRegion/TrustRegionSubProblem.cs
+++ b/src/Numerics/Optimization/TrustRegion/TrustRegionSubProblem.cs
@@ -2,16 +2,36 @@
namespace MathNet.Numerics.Optimization.TrustRegion
{
+ ///
+ /// Provides factory methods for creating instances of trust region subproblems.
+ ///
public static class TrustRegionSubproblem
{
+ ///
+ /// Creates an instance of the trust region subproblem using the dogleg algorithm.
+ ///
+ /// An implementation of based on the dogleg method.
public static ITrustRegionSubproblem DogLeg()
{
return new DogLegSubproblem();
}
+ ///
+ /// Creates an instance of the trust region subproblem using the Newton-Conjugate-Gradient algorithm.
+ ///
+ /// An implementation of based on the Newton-CG method.
public static ITrustRegionSubproblem NewtonCG()
{
return new NewtonCGSubproblem();
}
+
+ ///
+ /// Creates an instance of the trust region subproblem using the Exact algorithm with eigenvalue decomposition.
+ ///
+ /// An implementation of based on the Exact method.
+ public static ITrustRegionSubproblem Exact()
+ {
+ return new ExactSubproblem();
+ }
}
}