diff --git a/docs/source/vmcon.rst b/docs/source/vmcon.rst index 0fb096a..d00e259 100644 --- a/docs/source/vmcon.rst +++ b/docs/source/vmcon.rst @@ -26,8 +26,10 @@ Several facts are worth noting about problem formulation: The Lagrangian -------------- -VMCON is an augmented Lagrangian solver which means it uses the Lagrange multipliers, :math:`\vec{\lambda}`, of some -solution to characterise the quality of the solution. +VMCON is a sequential quadratic programming solver, meaning it solves a quadratic sub-problem at each iteration to find the search direction; a +line-search is used along this direction to determine an appropriate step length, reducing the impact of poor starting conditions. The quadratic +program solved at each iteration attempts to find the search direction that will minimise a quadratic approximation of the Lagrangian +(i.e. the search direction that balances minimising the objective function while satisfying the linearised constraints). Of specific note is the Lagrangian function: @@ -56,7 +58,7 @@ We also set the iteration number to 1, :math:`j=1`. The Quadratic Programming Problem --------------------------------- The Quadratic Programming Problem (QPP) will also be known as the Quadratic Sub-Problem (QSP) because it forms only a part of the -VMCON algorithm--with the other half being the Augmented Lagrangian. +VMCON algorithm. The function :math:`Q(\delta)` is a quadratic approximation of the Lagrangian function. Minimising :math:`Q(\delta)` subject to a linearisation of our constraints about :math:`\vec{x}_{j-1}` (aka solving the QPP) @@ -128,7 +130,7 @@ Once the line search exits, we have found our optimal value and :math:`\alpha_j On each iteration of the line search, we revise :math:`\alpha` using a quadratic approximation: .. math:: - \alpha = min\left(0.1\alpha, \frac{-\alpha^2}{\phi(\alpha) - \phi(0) - \alpha(\phi(1) - \phi(0))}\right) + \alpha = min\left(0.1\alpha, \frac{-0.5\alpha^2}{\phi(\alpha) - \phi(0) - \alpha(\phi(1) - \phi(0))}\right) The Broyden-Fletcher-Goldfarb-Shanno (BFGS) Quasi-Newton Update diff --git a/src/pyvmcon/problem.py b/src/pyvmcon/problem.py index 599b7d5..d198503 100644 --- a/src/pyvmcon/problem.py +++ b/src/pyvmcon/problem.py @@ -19,7 +19,12 @@ @dataclass class Result: - """The data from calling a problem.""" + """The data from calling a problem. + + .. deprecated:: 2.4.2 + Result is now a dataclass so should not be iterated over + (including tuple unpacking the object). + """ f: ScalarType """Value of the objective function.""" @@ -42,8 +47,8 @@ def __iter__(self) -> Iterator[ScalarType | VectorType | MatrixType]: """Convert the dataclass into an iterable. .. deprecated:: 2.4.2 - Result is now a dataclass so should not be iterated over - (including tuple unpacking the object). + Result is now a dataclass so should not be iterated over + (including tuple unpacking the object). """ warnings.warn( "Using the Result class as a namedtuple is deprecated (e.g. by tuple " @@ -108,6 +113,10 @@ class Problem(AbstractProblem): Note that VMCON assumes minimisation of f and that inequality constraints are feasible when they return a value >= 0. + + .. deprecated:: 2.4.2 + Problem is now a dataclass so should not be iterated over + (including tuple unpacking the object). """ f: _ScalarReturnFunctionAlias @@ -155,8 +164,8 @@ def __iter__( """Convert the dataclass into an iterable. .. deprecated:: 2.4.2 - Problem is now a dataclass so should not be iterated over - (including tuple unpacking the object). + Problem is now a dataclass so should not be iterated over + (including tuple unpacking the object). """ warnings.warn( "Using the Problem class as a namedtuple is deprecated (e.g. by tuple " diff --git a/src/pyvmcon/vmcon.py b/src/pyvmcon/vmcon.py index 427b6bf..76ac235 100644 --- a/src/pyvmcon/vmcon.py +++ b/src/pyvmcon/vmcon.py @@ -67,13 +67,13 @@ def solve( Initial estimate of the Hessian matrix `B`. If `None`, `B` is the identity matrix of shape `(n, n)`. - callback : Optional[Callable[[int, ndarray, Result], None]] + callback : Callable[[int, Result, VectorType, float], None] | None A callable which takes the current iteration, the `Result` of the current design point, current design point, and the convergence parameter as arguments and returns `None`. This callable is called each iteration after the QSP is solved but before the convergence test. - additional_convergence : Optional[Callable[[Result, ndarray, ndarray, ndarray, ndarray], None]] + additional_convergence : Callable[[Result, VectorType, VectorType, VectorType, VectorType], bool] | None A callabale which takes: the `Result` of the current design point, the current design point, the proposed search direction for the next design point, the equality Lagrange multipliers, and the @@ -102,6 +102,10 @@ def solve( The result from running the solution vector through the problem. """ # noqa: E501 + if not max_iter > 0: + error_msg = "max_iter must be greater than 0." + raise ValueError(error_msg) + if len(x.shape) != 1: error_msg = "Input vector `x` is not a 1D array" raise ValueError(error_msg)