GALAHAD LSTR package#
purpose#
The lstr
package uses a Krylov-subspace iteration to find an
approximation of the global minimizer of the
linear sum-of-squares objective function
within a sphere; this is commonly known as the
linear least-squares trust-region subproblem.
The aim is to minimize the least-squares objective function
See Section 4 of $GALAHAD/doc/lstr.pdf for additional details.
method#
The required solution \(x\) necessarily satisfies the optimality condition \(A^T ( A x - b ) + \lambda x = 0\), where \(\lambda \geq 0\) is a Lagrange multiplier corresponding to the trust-region constraint \(\|x\|_2 \leq \Delta\).
The method is iterative. Starting with the vector \(u_1 = b\), a bi-diagonalisation process is used to generate the vectors \(v_k\) and \(u_k+1\) so that the \(n\) by \(k\) matrix \(V_k = ( v_1 \ldots v_k)\) and the \(m\) by \((k+1)\) matrix \(U_k = ( u_1 \ldots u_{k+1})\) together satisfy
If the trust-region constraint is inactive, the solution \(y_k\) may be found, albeit indirectly, via the LSQR algorithm of Paige and Saunders which solves the bi-diagonal least-squares problem
If the solution is so constrained, the simplest strategy is to interpolate the last interior iterate with the newly discovered exterior one to find the boundary point — the so-called Steihaug-Toint point — between them. Once the solution is known to lie on the trust-region boundary, further improvement may be made by solving
references#
A complete description of the unconstrained case is given by
C. C. Paige and M. A. Saunders, ``LSQR: an algorithm for sparse linear equations and sparse least squares’’. ACM Transactions on Mathematical Software 8(1 (1982) 43–71,
and
C. C. Paige and M. A. Saunders, ``ALGORITHM 583: LSQR: an algorithm for sparse linear equations and sparse least squares’’. ACM Transactions on Mathematical Software 8(2) (1982) 195–209.
Additional details on how to proceed once the trust-region constraint is encountered are described in detail in
C. Cartis, N. I. M. Gould and Ph. L. Toint, ``Trust-region and other regularisation of linear least-squares problems’’. BIT 49(1) (2009) 21-53.
introduction to function calls#
To solve a given problem, functions from the lstr package must be called in the following order:
lstr_initialize - provide default control parameters and set up initial data structures
lstr_read_specfile (optional) - override control values by reading replacement values from a file
lstr_import_control - import control parameters prior to solution
lstr_solve_problem - solve the problem by reverse communication, a sequence of calls are made under control of a status parameter, each exit either asks the user to provide additional informaton and to re-enter, or reports that either the solution has been found or that an error has occurred
lstr_information (optional) - recover information about the solution and solution process
lstr_terminate - deallocate data structures
See the examples section for illustrations of use.
parametric real type T#
Below, the symbol T refers to a parametric real type that may be Float32 (single precision) or Float64 (double precision).
callable functions#
function lstr_initialize(T, data, control, status)
Set default control values and initialize private data
Parameters:
data |
holds private internal data |
control |
is a structure containing control information (see lstr_control_type) |
status |
is a scalar variable of type Int32 that gives the exit status from the package. Possible values are (currently):
|
function lstr_read_specfile(T, control, specfile)
Read the content of a specification file, and assign values associated with given keywords to the corresponding control parameters. An in-depth discussion of specification files is available, and a detailed list of keywords with associated default values is provided in $GALAHAD/src/lstr/LSTR.template. See also Table 2.1 in the Fortran documentation provided in $GALAHAD/doc/lstr.pdf for a list of how these keywords relate to the components of the control structure.
Parameters:
control |
is a structure containing control information (see lstr_control_type) |
specfile |
is a one-dimensional array of type Vararg{Cchar} that must give the name of the specification file |
function lstr_import_control(T, control, data, status)
Import control parameters prior to solution.
Parameters:
control |
is a structure whose members provide control parameters for the remaining procedures (see lstr_control_type) |
data |
holds private internal data |
status |
is a scalar variable of type Int32 that gives the exit status from the package. Possible values are (currently):
|
function lstr_solve_problem(T, data, status, m, n, radius, x, u, v)
Solve the trust-region least-squares problem using reverse communication.
Parameters:
data |
holds private internal data |
status |
is a scalar variable of type Int32 that gives the entry and exit status from the package. This must be set to
Possible exit values are:
|
m |
is a scalar variable of type Int32 that holds the number of equations (i.e., rows of \(A\)), \(m > 0\) |
n |
is a scalar variable of type Int32 that holds the number of variables (i.e., columns of \(A\)), \(n > 0\) |
radius |
is a scalar of type T that holds the trust-region radius, \(\Delta > 0\) |
x |
is a one-dimensional array of size n and type T that holds the solution \(x\). The j-th component of |
u |
is a one-dimensional array of size m and type T that should be used and reset appropriately when status = 1 to 5 as directed by status. |
v |
is a one-dimensional array of size n and type T that should be used and reset appropriately when status = 1 to 5 as directed by status. |
function lstr_information(T, data, inform, status)
Provides output information
Parameters:
data |
holds private internal data |
inform |
is a structure containing output information (see lstr_inform_type) |
status |
is a scalar variable of type Int32 that gives the exit status from the package. Possible values are (currently):
|
function lstr_terminate(T, data, control, inform)
Deallocate all internal private storage
Parameters:
data |
holds private internal data |
control |
is a structure containing control information (see lstr_control_type) |
inform |
is a structure containing output information (see lstr_inform_type) |
available structures#
lstr_control_type structure#
struct lstr_control_type{T} f_indexing::Bool error::Int32 out::Int32 print_level::Int32 start_print::Int32 stop_print::Int32 print_gap::Int32 itmin::Int32 itmax::Int32 itmax_on_boundary::Int32 bitmax::Int32 extra_vectors::Int32 stop_relative::T stop_absolute::T fraction_opt::T time_limit::T steihaug_toint::Bool space_critical::Bool deallocate_error_fatal::Bool prefix::NTuple{31,Cchar}
detailed documentation#
control derived type as a Julia structure
components#
Bool f_indexing
use C or Fortran sparse matrix indexing
Int32 error
error and warning diagnostics occur on stream error
Int32 out
general output occurs on stream out
Int32 print_level
the level of output required is specified by print_level
Int32 start_print
any printing will start on this iteration
Int32 stop_print
any printing will stop on this iteration
Int32 print_gap
the number of iterations between printing
Int32 itmin
the minimum number of iterations allowed (-ve = no bound)
Int32 itmax
the maximum number of iterations allowed (-ve = no bound)
Int32 itmax_on_boundary
the maximum number of iterations allowed once the boundary has been encountered (-ve = no bound)
Int32 bitmax
the maximum number of Newton inner iterations per outer iteration allowe (-ve = no bound)
Int32 extra_vectors
the number of extra work vectors of length n used
T stop_relative
the iteration stops successfully when \(\|A^Tr\|\) is less than max( stop_relative \* \(\|A^Tr_{initial} \|\), stop_absolute )
T stop_absolute
see stop_relative
T fraction_opt
an estimate of the solution that gives at least .fraction_opt times the optimal objective value will be found
T time_limit
the maximum elapsed time allowed (-ve means infinite)
Bool steihaug_toint
should the iteration stop when the Trust-region is first encountered?
Bool space_critical
if .space_critical true, every effort will be made to use as little space as possible. This may result in longer computation time
Bool deallocate_error_fatal
if .deallocate_error_fatal is true, any array/pointer deallocation error will terminate execution. Otherwise, computation will continue
NTuple{31,Cchar} prefix
all output lines will be prefixed by .prefix(2:LEN(TRIM(.prefix))-1) where .prefix contains the required string enclosed in quotes, e.g. “string” or ‘string’
lstr_inform_type structure#
struct lstr_inform_type{T} status::Int32 alloc_status::Int32 bad_alloc::NTuple{81,Cchar} iter::Int32 iter_pass2::Int32 biters::Int32 biter_min::Int32 biter_max::Int32 multiplier::T x_norm::T r_norm::T Atr_norm::T biter_mean::T
detailed documentation#
inform derived type as a Julia structure
components#
Int32 status
return status. See lstr_solve_problem for details
Int32 alloc_status
the status of the last attempted allocation/deallocation
NTuple{81,Cchar} bad_alloc
the name of the array for which an allocation/deallocation error occurred
Int32 iter
the total number of iterations required
Int32 iter_pass2
the total number of pass-2 iterations required if the solution lies on the trust-region boundary
Int32 biters
the total number of inner iterations performed
Int32 biter_min
the smallest number of inner iterations performed during an outer iteration
Int32 biter_max
the largestt number of inner iterations performed during an outer iteration
T multiplier
the Lagrange multiplier, \(\lambda\), corresponding to the trust-region constraint
T x_norm
the Euclidean norm of \(x\)
T r_norm
the Euclidean norm of \(Ax-b\)
T Atr_norm
the Euclidean norm of \(A^T (Ax-b) + \lambda x\)
T biter_mean
the average number of inner iterations performed during an outer
iteration
example calls#
This is an example of how to use the package to solve a linear least-squares trust-region problem; the code is available in $GALAHAD/src/lstr/Julia/test_lstr.jl .
# test_lstr.jl
# Simple code to test the Julia interface to LSTR
using GALAHAD
using Test
using Printf
using Accessors
function test_lstr(::Type{T}) where T
# Derived types
data = Ref{Ptr{Cvoid}}()
control = Ref{lstr_control_type{T}}()
inform = Ref{lstr_inform_type{T}}()
# Set problem data
n = 50 # dimensions
m = 2 * n
status = Ref{Cint}()
radius = Ref{T}()
x = zeros(T, n)
u = zeros(T, m)
v = zeros(T, n)
# Initialize lstr
lstr_initialize(T, data, control, status)
# resolve with a smaller radius ?
for new_radius in 0:1
if new_radius == 0 # original radius
radius[] = 1.0
status[] = 1
else # smaller radius
radius[] = 0.1
status[] = 5
end
@reset control[].print_level = Cint(0)
lstr_import_control(T, control, data, status)
for i in 1:m
u[i] = 1.0 # b = 1
end
# iteration loop to find the minimizer with A^T = (I:diag(1:n))
terminated = false
while !terminated # reverse-communication loop
lstr_solve_problem(T, data, status, m, n, radius[], x, u, v)
if status[] == 0 # successful termination
terminated = true
elseif status[] < 0 # error exit
terminated = true
elseif status[] == 2 # form u <- u + A * v
for i in 1:n
u[i] = u[i] + v[i]
u[n + i] = u[n + i] + (i + 1) * v[i]
end
elseif status[] == 3 # form v <- v + A^T * u
for i in 1:n
v[i] = v[i] + u[i] + (i + 1) * u[n + i]
end
elseif status[] == 4 # restart
for i in 1:m
u[i] = 1.0
end
else
@printf(" the value %1i of status should not occur\n",
status)
end
end
lstr_information(T, data, inform, status)
@printf("%1i lstr_solve_problem exit status = %i, f = %.2f\n", new_radius,
inform[].status, inform[].r_norm)
end
# Delete internal workspace
lstr_terminate(T, data, control, inform)
return 0
end
@testset "LSTR" begin
@test test_lstr(Float32) == 0
@test test_lstr(Float64) == 0
end