Documentation | License | Build Status | Code Coverage |
---|---|---|---|
OptimPack.jl is the Julia interface to OptimPack, a C library for solving large scale optimization problems.
From a Julia session, press ]
to enter the Pkg REPL and type the following commands:
(...) pkg> add https://github.com/emmt/OptimPack.jl
to install and build the package. This just has to be done once.
To use the package in your code:
using OptimPack
By default, the package manager will attend to download precompiled OptimPack
libraries for your architecture so that you have nothing to compile. These
libraries are provided by the
OptimPackBuilder project. If your
system is not part of the supported platforms or if you want to use
OptimPack libraries compiled and installed by yourself (see intructions at
official OptimPack repository) then you have to define 4
environment variables before building OptimPack.jl
package. Each of
these environment variables specifies the full path to one of the OptimPack
dynamic libraries. These environment variables can be set before starting Julia
or at Julia REPL, for instance by:
ENV["OPTIMPACK_OPK_LIB"] = "/usr/local/lib/libopk.so"
ENV["OPTIMPACK_COBYLA_LIB"] = "/usr/local/lib/libcobyla.so"
ENV["OPTIMPACK_BOBYQA_LIB"] = "/usr/local/lib/libbobyqa.so"
ENV["OPTIMPACK_NEWUOA_LIB"] = "/usr/local/lib/libnewuoa.so"
Then proceed as for the other installation method: press ]
to enter the Pkg
REPL and type the following commands:
(...) pkg> add https://github.com/emmt/OptimPack.jl
You may use URL git@github.com:emmt/OptimPack.jl
if you want to use SSH
instead of HTTPS.
If you define the environment variables after adding OptimPack.jl
package,
just re-build the package:
(...) pkg> build OptimPack
There are two methods in OptimPack to minimize a nonlinear smooth multivariate
function without constraints: non-linear conjugate gradient (NLCG) implemented
by nlcg
and limited memory variable metric method (VMLM) implemented by
vmlm
. In general, vmlm
is more efficient than nlcg
but may require more
memory.
The easiest way to use these minimizers is to provide a Julia function, say
fg!
, which is in charge of computing the value of the function and its
gradient for given variables. This function must have the form:
function fg!(x, g)
g[...] = ... # store the gradient of the function
f = ... # compute the function value
return f # return the function value
end
where the arguments x
and g
are Julia arrays (same types and
dimensions) with, on entry, x
storing the variables and, on exit, g
storing the gradient. The user defined function shall return the function
value.
The solution x
can be computed by one of the implemented nonlinear
conjugate gradient methods with:
x = nlcg(fg!, x0, method)
where x0
gives the initial value of the variables (as well as the data
type and dimensions of the solution). x0
is a Julia dense array with any
dimensions and with elements of type Float64
or Float32
. Argument
method
is optional and can be used to choose among the different implemented
methods (see below).
The keyword verb
can be set true to print information at each iteration.
Other keywords are described in the following sub-sections.
The different nonlinear conjugate gradient methods mainly differ by the way they compute the search direction. The conjugate gradient iteration writes:
x_{k+1} = x_{k} + alpha_{k} * d_{k}
with alpha_{k}
the step length and where the search direction d_{k}
is
derived from the gradient g(x_{k})
of the objective function at the
current point x_{k}
and from the previous search direction d_{k-1}
by
an update rule which depends on the specific method. Typically:
d_{k} = -g(x_{k}) + beta_{k} * d_{k-1}
where beta_{k}
is computed following different recipes. To choose which
recipe to use, the value of the method
argument can be set to one of the
following values:
OptimPack.NLCG_FLETCHER_REEVES
for Fletcher & Reeve method;OptimPack.NLCG_HESTENES_STIEFEL
for Hestenes & Stiefel method;OptimPack.NLCG_POLAK_RIBIERE_POLYAK
for Polak, Ribière & Polyak method;OptimPack.NLCG_FLETCHER
for Fletcher "Conjugate Descent" method;OptimPack.NLCG_LIU_STOREY
for Liu & Storey method;OptimPack.NLCG_DAI_YUAN
for Dai & Yuan method;OptimPack.NLCG_PERRY_SHANNO
for Perry & Shanno update rule;OptimPack.NLCG_HAGER_ZHANG
for Hager & Zhang method.
The above values can be bitwise or'ed with the following bits:
OptimPack.NLCG_POWELL
to force parameterbeta
to be nonnegative;OptimPack.NLCG_SHANNO_PHUA
to guess the step length following the prescription of Shanno & Phua.
For instance:
method = OptimPack.NLCG_POLAK_RIBIERE_POLYAK | OptimPack.NLCG_POWELL
merely corresponds to PRP+ algorithm by Polak, Ribière & Polyak; while:
method = OptimPack.NLCG_PERRY_SHANNO | OptimPack.NLCG_SHANNO_PHUA
merely corresponds to the nonlinear conjugate gradient method implemented in CONMIN (Shanno & Phua, 1980).
The default settings for nonlinear conjugate gradient is:
const OptimPack.NLCG_DEFAULT = (OptimPack.NLCG_HAGER_ZHANG | OptimPack.NLCG_SHANNO_PHUA)
The nonlinear conjugate gradient methods are iterative algorithms, the convergence is assumed to be achieved when the Euclidean norm of the gradient is smaller than a threshold. In pseudo-code, the criterion is:
||g(x)|| <= max(0, gatol, grtol*||g(x0)||)
where ||g(x)||
is the Euclidean norm of the gradient at the current
solution x
, ||g(x0)||
is the Euclidean norm of the initial gradient at
x0
, gatol
is an absolute threshold parameter and grtol
is a relative
threshold parameter. The keywords gatol
and grtol
can be used to
specify other values for these parameters than the default ones which are
gatol = 0.0
and grtol = 1E-6
.
It may be desirable to limit the time spent by the algorithm. To that end,
the keywords maxiter
and maxeval
are available to specify the maximum
number of iterations and evaluations of the algorithm respectively. Their
default values is -1
which means that there are no restrictions. For now,
the algorithm can only be safely stopped at an acceptable iterate, thus the
maximum number of allowed function evaluations may slightly exceed the
value of maxeval
.
The keyword lnsrch
can be used to specify another line search method than
the default one:
x = nlcg(fg!, x0, method, lnsrch=ls)
where ls
is one of the implemented line search methods:
ls = OptimPack.ArmijoLineSearch(ftol=...)
ls = OptimPack.MoreThuenteLineSearch(ftol=..., gtol=..., xtol=...)
ls = OptimPack.NonmonotoneLineSearch(mem=..., ftol=..., amin=..., amax=...)
with ftol
the tolerance on the function reduction for the Armijo or first
Wolfe condition, gtol
the tolerance on the gradient for the second
(strong) Wolfe condition, xtol
the relative precision for the step length
(set to the machine relative precision by default), mem
the number of
previous steps to remember for the nonmonotone line search, keywords amin
and amax
set the lower steplength bound and the upper steplength relative
bound to trigger bissection in nonmonotone line search. By default, the
values used in SPG2 are used for the nonmonotone line search: mem = 10
,
ftol = 1E-4
, amin = 0.1
and amax = 0.9
.
The line search is safeguarded by imposing lower and upper bounds on the
step. In nlcg
and vmlm
, keywords stpmin
and stpmax
can be used to
specify the step bounds relatively to the size of the first step for each
line search. Their default values are: stpmin = 1E-20
and stpmax = 1E+20
; if specified, they must be such that: 0 <= stpmin < stpmax
.
Alternatively, the solution x
can be computed by a limited memory version
of the variable metric method (implementing BFGS updates) with:
x = vmlm(fg!, x0, m)
where the optional argument m
is the number of previous steps to memorize
(by default m = 3
) while other arguments have the same meaning as for
nlcg
.
Keywords verb
, gatol
, grtol
, lnsrch
, stpmin
and stpmax
can also
be specified for vmlm
and have the same meaning as for nlcg
.
In addition to these keywords, you can specify how to scale the inverse
Hessian in variable metric method via the scaling
keyword:
scaling = OptimPack.SCALING_NONE # to use a unit scaling (no scaling)
scaling = OptimPack.SCALING_OREN_SPEDICATO # to scale by: gamma1 = <s,y>/<y,y>
scaling = OptimPack.SCALING_BARZILAI_BORWEIN # to scale by: gamma2 = <s,s>/<s,y>
where <s,y>
denotes the inner product between the previous step s
and
gradient difference y
.
The spectral projected gradient (SPG2) method of Birgin, Martinez & Raydan can be used for solving large constrained optimization problems. The usage of the SPG2 method is documented here.
To create a vector space for vectors of dimensions dims
and element type
T
:
space = OptimPack.DenseVectorSpace(T, dims)
where T
is Float32
or Float64
(or any type alias of these,
e.g. Cfloat
or Cdouble
) and dims
is a tuple of the dimensions.
It is also possible to wrap a vector around a specific Julia array:
vect = OptimPack.wrap(space, arr)
where space
is an OptimPack shaped vector space and arr
is a Julia
array. The element type and dimension list of the array must match those
of the vector space. A method is available to change the contents of such
a vector:
OptimPack.wrap!(vect, arr2)
where arr2
is another Julia array (the same constraints on the element
type and dimensions apply).
Note that arr
must be a dense array (of type DenseArray
) as the
elements of shaped vectors are supposed to be stored contiguously in
memory. OptimPack offers the possibility to create custom vector spaces
and this will be exploited in a near future to allow for other flavors of
Julia arrays.
Run-time errors throw Julia exception.