Figure 2 shows a classification of the optimization
methods included in the preliminary release of the library.
Except for the linear solvers, all methods can communicate with
user-supplied objective functions.
For algorithms such as conjugate gradient, the required gradient
information can be suppied by the user if it is available, otherwise
COOOL will compute it numerically by finite differences.
Using the freely available package EXPECT, we are able to use an
especially simple model of communication between the optimization
methods and the objective function for obtaining information on both
function values and their derivatives.
This is illustrated in Figure 3.
The model consists of a list of
numbers
,
up to
. The optimization routine first sends out a flag which tells
the objective function whether it requests a function value or a
gradient vector, followed by these
numbers to its standard output; the
objective function then reads the
numbers from its standard
input, computes the function value or gradient vector according to the
request, and writes that to its standard output; finally, the optimization
routine captures the objective function value or gradients via its own
standard input and then decides how to update the model.
This simple model allows us to consider algorithms as diverse as
conjugate gradient and simulated annealing within a unified framework.
:
An overview of the optimization
algorithms contained in COOOL (see text below). Included are
linear solvers for rectangular linear systems using both least
squares and general
norms and local methods based on direct
search and quasi-Newton methods. Monte Carlo global optimization
methods will be part of a future release of COOOL.
: A model of communication between the objective function
and the optimization routine.
Each
objective function consists of a stand-alone program which reads models
from its standard input and writes numbers to its standard output.
A key point is that the communication between the optimization routine and the objective function is transparent to the user. If you want to use one of the optimization methods on your own objective function, all you have to do is write the objective function as a stand-alone program which reads a flag followed by a model from standard input and writes a number to standard output-until an end-of-file is reached. On the other hand, if you want to add your own optimization algorithm to the library, you do not have to know how this communication mechanism works. Your application can still take advantage of this communication capability by declaring an instance of an objective function class within the optimization code. (Instantiation is the Object-Oriented Programming (OOP) jargon for this. The closest C analog of this would be to declare a variable as being of a given type. But in C++, instantiation of an object may result in the execution of complex instructions.) The objective function class inherits the ability to perform this communication.
The linear solvers are really a separate issue. The codes are written in the same OOP style as the rest of the optimization methods, and therefore benefit from the same ideas of encapsulation, inheritance, etc. (see below). However, they require the specification of a matrix, which is often huge and sparse.