Interfacing New Target Functions to NewOpt
Introduction
This document describes the how to use the newopt optimiser to
optimise a general target function. In short, a number of Tcl wrappers
are provided for the target function, each named according to conventions
described below, with a common prefix. Then newopt can be invoked using
the prefix as the function= argument.
The following sections describe the function and interfaces of each of
these Tcl procedures. In each case, only the suffix of the procedure
name is given. This is appended to a root name, which corresponds to
the function= argument provided to newopt.
For example,
newopt function=test : { coords=c list_option=full }
would invoke procedures of the form test.dimension, test.initx etc. The arguments
coords=c and list_option=full would be passed through to each of these procedures.
Obligatory Functions
.dimension
Requirement Return (as it's Tcl result string) the number of
variables in the optimisation problem. Since this is the first procedure
called, it would be normal practice to set up any internal data structures
at this point.
.initx
Requirement Set the elements of the ChemShell matrix object
x (which will be allocated prior to the procedure call) to the starting values
of the optimisation parameters.
All functions should accept an argument prefix= which will be set
to the name of the optimiser object controlling the optimisation. All matrices
holding optimisation variables will be prefixed by the optimiser name, followed
by a full stop. In subsequent function descriptions it is assumed that the
variable opt is set to the name of the optimiser object.
.value
Requirement From the setting of the current parameters in ChemShell matrix
object $opt.x, compute the value of the function and store in matrix object $opt.f.
.kill
Requirement Clean up after a run, release memory etc.
Optional Functions
The following procedures may be provided, but if they are missing the
program should continue. Of course, the analytic derivative functions are
almost essential.
.deriv
Requirement From the setting of the current parameters in ChemShell matrix
object $opt.x, compute the value of the derivative function and store in matrix object $opt.g.
If the function is missing a finite difference approach will be taken to the
gradient calculation
.vandd
Requirement Combine the functions of the .value and .deriv procedures.
If the function is missing a finite difference approach will be taken to the
gradient calculation
.hessian Requirement Compute the current second
derivative matrix from the current value of the vector $opt.x, and store in
the ChemShell matrix object $opt.h. If the function is missing a finite
difference approach will be taken.
.guesshess
Requirement Store an approximate hessian in the ChemShell object $opt.h.
If this function is missing, the hessian command with the method=guess
argument won't work.
.varname
Requirement Return (as the Tcl result string) the name of
one of the optimisation variables. The procedure should accept
the index= argument to define which variable name to report. Indexing
starts counting from 0.
.set
Requirement Refresh any user-visible objects that depend on
the current position (the vector $opt.x) to reflect the current value of
this vector. It is valid for this function to have no effect, but
often there will be other objects that change with the progress of the
optimisation and if the contents of these objects are likely to be
visible to the user, they should be modified by the .set
procedure. Typically the .set function is used after a finite
difference procedure to ensure a displaced geometry is not picked up
by accident.
An example is the case of a molecular structure
optimisation. NewOpt maintains the structure as a simple vector (ie
$opt.x), however the family of procedures implementing the energy and
gradient calculations will build a ChemShell fragment object prior to
each energy evaluation, to pass to the respective routines. At each
point in an optimisation this structure will reflect the progress of
the run, and may be useful for visualisation. However, if a finite
difference procedure has just completed, the last structure for which
an energy has been evaluated may not represent a point on the
optimisation pathway. In such cases a call to the .set function will
be made by the optimiser, to enable the correct structure to be
restored.
Note that implementation of the .set function is optional,
since NewOpt will retains the correct vector $opt.x internally.
.write
Requirement Convert the current value of the $opt.x vector to an object of
the appropriate type for user examination.
The procedure should accept an argument mode= (ChemShell syntax) which
is used to determine the file name to save the current point. The naming
convention is up to the user since these structures are not recovered by
NewOpt.
The four values of the mode argument that are currently employed are:
- mode=result [ default , the end point of the optimisation ]
- mode=best [ the best point so far on the pathway ]
- mode=start [ the initial structure ]
- mode=vis [ for visualisation ]
The implementation of this procedure is optional, if it is missing the
value of $opt.x will be written out as a matrix object (x.best etc).
.punch
Requirement Append the current point to a punchfile (e.g. a sequence of
structures for animation.
Example
The following target function is a simple 1-D quadratic.
proc quad.dimension {args} {
return 1
}
proc quad.initx {args} {
global prefix
parsearg quad {prefix} $args
set_matrix_element matrix=$prefix.x indices= {0 0} value=-3.0
}
proc quad.value {args} {
global prefix
set x0 [ get_matrix_element matrix=$prefix.x indices= {0 0} format=%20.14e ]
set_matrix_element matrix=$prefix.f indices= {0 0} value= [ expr 7.0 + 3.0*$x0 + 2.0*$x0*$x0 ]
}
proc quad.deriv {args} {
global prefix
set x0 [ get_matrix_element matrix=$prefix.x indices= {0 0} format=%20.14e ]
set_matrix_element matrix=$prefix.f indices= {0 0} value= [ expr 7.0 + 3.0*$x0 + 2.0*$x0*$x0 ]
set_matrix_element matrix=$prefix.g indices= {0 0} value= [ expr 3.0+4.0*$x0 ]
}
proc quad.hessian {args} {
global prefix
set x0 [ get_matrix_element matrix=$prefix.x indices= {0 0} format=%20.14e ]
set_matrix_element matrix=$prefix.h indices= {0 0} value=4.0
}
|