NAG CPP Interface
Introduction
1
Introduction
The NAG CPP Interface is a set of C++ interfaces for the NAG Library, supplied as a series of header files. The supplied material is laid out as follows:
installation-directory |
|
|
include |
|
|
This directory, and its subdirectories, contain the header files that make up the bulk of the NAG CPP Interface. |
| |
|
|
z00 |
|
|
|
There are a number of directories named after the chapters of the NAG Library, for example e04, g01 etc.. The header files for the available functions are split by chapter, with each function in its own file. These header files contain wrappers which directly call the algorithmic engine and as such do minimal computation themselves. |
|
|
The header files use a naming convention based on the short NAG name of the NAG Library function, for example handle_solve_lp_ipm is in Chapter E04 and has a short NAG name of e04mt and so the associated header file is ‘nagcpp_e04mt.hpp’ and sits in the e04 subdirectory. |
|
|
In addition to the individual function header files these directories may also include a number of files defining communication classes. The naming convention adopted here is based on the short NAG name of the NAG Library function that initializes the communication information. For example, handle_init initializes the communication information required by a number of functions in Chapter E04, including handle_solve_dfls_rcomm, handle_solve_lp_ipm and handle_solve_ipopt. The associated communication class, CommE04RA, is defined in ‘nagcpp_class_CommE04RA.hpp’ in the e04 subdirectory. |
| |
|
|
utility |
|
|
|
A series of header files containing various utility classes and functions. |
|
In addition to the subdirectories described above, this directory contains a header file per chapter, which brings together all the functions from that chapter, and a master header file which includes all functions from all chapters. |
|
|
example |
|
|
This directory contains example files showing how to call a number of the available functions. Each example file can be individually compiled and run (see Section 2.1.5 for more details). |
| |
|
|
baseresults |
|
|
|
This directory contains the expected results from each of the examples. In cases where a different implementation of the NAG Library may cause an example to give slightly different output, multiple results files are present. |
| |
|
|
include |
|
|
|
This directory contains some example data container classes. These files demonstrate one way to pass a custom class as an argument to the NAG Library (see Section 3.2 for more details) and are used by some of the examples. |
|
|
tests |
|
|
This directory contains a number of unit tests for various aspects of the NAG CPP Interface . It should be noted that these tests are only for the wrappers and so do not test the underlying algorithmics. Each unit test can be individually compiled and run. |
| |
|
|
include |
|
|
|
This directory contains a number of utilities used by the unit tests. |
Prior to using the NAG CPP Interface you will need to have a version of Mark 30 of the NAG Library installed.
When using the interfaces supplied via the NAG CPP Interface you will need to add the
include subdirectory to the list of directories your compiler searches for header files, in addition to using any compiler flags usually required by the NAG Library.
2
The NAG Library Documentation
The
Guide to the NAG Library Documentation provides general information on how to use the NAG Library documentation; the following sections are specific to the NAG CPP Interface.
2.1
Function Documentation
2.1.1
Classification of Arguments (Intents)
Arguments are classified as follows.
- input: unless stated otherwise in the individual function documentation, you must assign values to these arguments on or before calling the function, and these values are unchanged on exit from the function.
- output: you need not assign values to these arguments before calling the function; unless stated otherwise in the individual function documentation the function will assign values to them on exit. If possible the function will allocate array arguments to the correct size (see Section 2.1.3).
- input/output: unless stated otherwise in the individual function documentation, you must assign values to these arguments before calling the function, and the function may then change these values. For array arguments where the individual function documentation indicates that no values must be supplied on entry but that values are returned on exit, the function will attempt to allocate the argument to the correct size (see Section 2.1.3).
- Function: unless stated otherwise in the individual function documentation you must supply a callback function (e.g., to evaluate an integrand or to print intermediate output). The prototype for the callback function is given in the individual function documentation and includes full details of its argument list and specifications of its arguments (all enclosed in a box). The arguments of a callback function are classified in a similar manner to above but, because you must write the function rather than call it, the significance of the classification is different.
- input: unless stated otherwise in the individual function documentation, values will be supplied on entry, which your function must not change.
- output: unless stated otherwise in the individual function documentation, you must assign values to these arguments before returning from your function.
- input/output: unless stated otherwise in the individual function documentation, values will be supplied on entry, and you must assign values to them before returning from your function.
In cases where an argument is not referenced or, in the case of callback functions, where a default function has been supplied by
NAG you should pass
nullptr as the corresponding argument. See
Section 10 in
handle_solve_ipopt for an example where a callback function is not referenced,
Section 10 in
handle_solve_lp_ipm for an example where a default callback function is used and
Section 10 in
lars for an example where an
input argument is set to
nullptr.
2.1.2
Constraints
The word ‘
Constraint:’ or ‘
Constraints:’ in the specification of an
input argument introduces a statement of the range of valid values for that argument, e.g.,
If the function is called with an invalid value for the argument (e.g.,
), the function will raise an error (see
Section 5).
Constraints on string arguments only list upper case characters, e.g.,
In practice, all functions with string arguments are case insensitive.
2.1.3
Array Arguments
The actual variable passed as an array argument to the function is referred to as a data container in this documentation.
The interfaces supplied with the NAG CPP Interface support a number of data containers (see
Section 3 for details), as such all array arguments are templated and this is shown within the documented function prototype. However, such arguments are described later in the documentation in terms of a non-templated type. The non-templated type is the data type that the underlying function from the algorithmic engine is expecting and hence the type of data that the supplied data container must supply. For example, in
quantiles, argument
rv is described as having type
RV in
Section 2 in
quantiles and being a
double array in
Section 5 in
quantiles. A data container supplied as
rv must hold the required data as a
double, for example a
std::vector<double> could be supplied.
The dimensions of array arguments are given in their description, for example a vector (a
one-dimensional array) argument may be described as:
indicating that the vector should be of length
, or a matrix (a
two-dimensional array) may be described as:
indicating that a
matrix should be supplied (i.e., a matrix with
rows and
columns).
A number of functions in the NAG Library take a table as an argument. Here we define a table as containing
,
matrices (i.e., a
three-dimensional array), which may be described in the documentation as:
When declaring array arguments, you must ensure that all dimensions are of the documented size, i.e., you may not supply oversized array arguments.
For
output array arguments, if a
resize method, or equivalent, has been supplied then the argument does not need to be pre-allocated to the correct size. If such a method is not supplied then you must pre-allocate the argument prior to calling the function (see
Section 3.2 for more details on the
resize method).
When describing individual elements of arrays, the notation , and is used for vectors, matrices and tables respectively, i.e., round brackets, . The indices used with this notation are zero based unless explicitly stated otherwise.
2.1.3.1
Callback Array Arguments
As with array arguments in the main wrapper, the interfaces supplied with the NAG CPP Interface support a number of data containers as arguments to callback functions. Unlike the array arguments in the main wrapper, when documenting callback functions, any arrays are described in terms of a particular
array1D,
array2D or
array3D (see for example
objfun). However, you can write your callback function using any of the supported data containers as described in
Section 3.
If implementing your own custom data container for use with the callback function (see
Section 3.3.2), the specialization of
array1D,
array2D or
array3D documented is the class types your specialization of
nagcpp::data_handling::convert_nag_array_to_user_t must handle.
2.1.4
Structure of the Error Messages
Any error or warning messages that a function may return are categorised by exception type (see for example
Section 6 in
contfn_brent). By default errors raised by a function will be thrown as exceptions, warnings will not. Details of any warnings raised can be obtained via
fail. See
Section 5 for details on how to change this behaviour.
The notation appearing in the documented error message is a place holder that will be populated by the value of a variable, argument name or some other piece of information when that error message is displayed.
2.1.5
Example Programs and Results
Where available, the
example program in the Example Section of the function document illustrates a simple call of the function. These example programs are distributed with the NAG CPP Interface in the
example subdirectory and the expected results in the
baseresults subdirectory.
For some example programs a number of alternative results files have been supplied, for example, ‘ex_e04mt.r’, ‘ex_e04mt.r_v1’, ‘ex_e04mt.r_v2’ are all results files obtained from running ‘ex_e04mt.cpp’ on different platforms. Only one of these results files (‘ex_e04mt.r’) will appear in the function documentation.
Note that even where variant results files have been supplied, the results you obtain may not agree exactly with any of the results files supplied, however any differences should be of a similar magnitude to that displayed between the variants.
Some examples use data container types that are only supported if that support is switched on (for example ‘ex_e04fg_boost.cpp’). See
Section 3.1 for information on how to do this.
2.2
Class Documentation
Documentation for several classes is provided. In many cases these classes contain members that are designed for use by the wrappers supplied by the NAG CPP Interface rather than directly. In such cases full documentation is only supplied for those members intended for direct use. Documentation for any other members will only be in the form of code comments.
Arguments to methods use the same classification of intent as described in
Section 2.1.1 and may containt constraint information as described in
Section 2.1.2.
2.3
Communication Class Documentation
Many functions in the NAG CPP Interface need to communicate with each other, for example, in order to solve an optimization problem using
handle_solve_ipopt you first need to set up the type of problem you wish to solve using one or more functions from
Chapter E04. The mechanism used to communicate between functions is via a series of communication classes, for example,
CommE04RA is used by
handle_solve_ipopt, amongst others. Each class follows a similar format.
Each communication class has its own documentation. These documents can be found by following the links in the documentation for the function you are interested in.
A number of example programs change optional parameters through the communication class, see for example
Section 10 in
handle_solve_lp_ipm and
Section 10 in
handle_solve_ipopt.
2.4
Implementation-dependent Information
In order to support all implementations of the NAG Library, the Manual has adopted a convention of using bold italics to distinguish terms which have different interpretations in different implementations.
One bold italicised term is machine precision, which denotes the relative precision to which real floating-point numbers are stored in the computer, e.g., in an implementation with approximately 16 decimal digits of precision, machine precision has a value of approximately .
The precise value of
machine precision is given by the function
precision.
3
Data Containers
As noted above, the actual variable passed as an array argument to the function is referred to as a data container in this documentation. The wrappers supplied by the NAG CPP Interface support a number of data containers. The type of data containers supported are divided into two groups, those supported as arguments to the main function interface and those supported as arguments to callback functions.
A list of supported data containers is given in
Section 3.1.
The wrappers supplied by the NAG CPP Interface can, in fact, support any arbitrary data container as long as that data container implements a number of standard methods (see
Section 3.2).
3.1
Supported Types
The following types are supported as arguments to both the main function interface and to callback functions:
- array1D
- array2D
- array3D
- std::vector<T>.
- boost::numeric::ublas::vector<T>, support for this type must be switched on by defining #HAVE_BOOST_VECTOR.
- boost::numeric::ublas::matrix<T>, support for this type must be switched on by defining #HAVE_BOOST_MATRIX.
where
T is either
double,
int or
string.
In a callback function it will usually be more efficient to use either
array1D,
array2D or
array3D. These classes work directly with the arrays used by the algorithmic engine, whereas
std::vector<T>,
boost::numeric::ublas::vector<T> and
boost::numeric::ublas::matrix<T> all require data to be copied in and out. Similarly, when used as an argument to the main function the following data containers require a full copy of the data to be made:
boost::numeric::ublas::vector<T> and
boost::numeric::ublas::matrix<T>.
The pre-processor variables like
#HAVE_BOOST_VECTOR can either be defined via compiler flags when compiling, or by uncommenting the corresponding entry in ‘nagcpp_available_data_containers.hpp’ in the
utility subdirectory.
3.2
Using Arbitrary Data Containers
The NAG CPP Interface support the use of any arbitrary data container as an argument to the main function interface, as long as that data container implements a number of standard methods. The methods required for a data container to be used as a vector (1D array) are described in
DummyVectorDataContainer, the methods required for it to be used as a matrix (2D array) are described in
DummyMatrixDataContainer and the methods required for it to be used as a table (3D array) are described in
DummyTableDataContainer.
When using an arbitrary data container, if data of the wrong type is supplied, i.e., the function documentation states that the array argument in question should supply data of type double, but the supplied data container is of type float, then the data is converted, using std::static_cast, and copied both into and out of the calls to the algorithmic engine.
Examples of data containers of each type are included in the
include subdirectory, along with a generic data container that can be used as any of the three types (as a 1D, 2D or 3D array).
Arbitrary data containers can
not be used as arguments to callback functions, only those data containers listed in
Section 3 can be used.
See
Section 3.3 for information on using data containers which do not implement the required standard methods and for information on using a custom data container as an argument in a callback function.
3.2.1
Storage Order
When designing a multi-dimensional data container for use with the NAG CPP Interface (i.e., anything other than a vector), the underlying storage used for the data must be considered. Ultimately the data container must deliver the data in a contiguous block of memory (for example, through the
data method). The algorithmic engine supports data stored in one of two ways, column-major order or row-major order.
For
, an
matrix, the value in the
th row and
th column must be stored in the
th element of the contiguous memory, with:
for
and
.
For a table containing
,
matrices (i.e., a
three-dimensional array), the value in the
th row and
th column of the matrix in the
th table must be stored in the
th element of the contiguous memory, with:
for
and
.
For performance reasons, it is usually preferable if the data is stored in column-major order.
If a function has multiple multi-dimensional array arguments then they must all use the same internal storage order, i.e., they must all be in column-major order or all in row-major order. Any multi-dimensional array in a callback function will have the storage order used when calling the main function. If the main function does not have any multi-dimensional array arguments then the default storage order is used as defined by
default_to_col_major.
3.3
Non-standard Data Containers
3.3.1
As Arguments to the Main Function
If you are unable or unwilling to implement the required standard methods in your data container then it can still be used as an argument to a function, however it will take a bit more work. In such a case a specialization of the
nagcpp::data_handling::RawData class must be supplied. What this entails is not documented here, however examples can be found in the
utility subdirectory in, for example, ‘nagcpp_data_handling_boost_matrix.hpp’ or ‘nagcpp_data_handling_boost_vector.hpp’.
Once you have implemented the specialization you can test that it performs as expected using one of the unit tests in the
tests subdirectory, specifically ‘ut_data_handling_1D.cpp’,
‘ut_data_handling_2D.cpp’ or ‘ut_data_handling_3D.cpp’. Code comments in the relevant file gives details on how to incorporate your own data container into the unit test. An example of the additional utility functions that you must supply can be found in the
include subdirectory in, for example ‘nagcpp_ut_boost_vector_setup.hpp’ and ‘nagcpp_ut_boost_vector_setup.hpp’.
3.3.2
As Arguments to a Callback Function
In order to use a non-supported data container as an argument in a callback function a specialization of the
nagcpp::data_handling::convert_nag_array_to_user_t must be supplied. What this entails is not documented here, however examples can be found in the
utility subdirectory in, for example, ‘nagcpp_data_handling_std_vector.hpp’, ‘nagcpp_data_handling_boost_matrix.hpp’ or ‘nagcpp_data_handling_boost_vector.hpp’.
Once the specialization has been implemented the same unit tests as described in
Section 3.3.1 can be used to test its functionality, and the same examples apply.
4
Optional Arguments
There are two types of optional arguments to functions in the NAG CPP Interface, those that are supplied through the communication class (
Section 2.3) and those that are no different to standard interface arguments, other than the fact that a sensible default value can be chosen. For example in the function
prob_students_t_noncentral, sensible default values can be chosen for both
tol and
maxit. Rather than being supplied directly in the function interface, such arguments are supplied via an optional argument class, which is unique to each function. Each optional argument is described in the individual function documentation.
Each optional argument class is a child of
Optional and as such can also be used for error handling and controlling file
input/output.
Each optional argument has two methods associated with it, a getter and a setter. The name of the setter method is based on the documented name of the optional argument, takes a single argument (the value to set the optional argument to) and returns a reference to the optional argument class (hence allowing the calls to be chained). For example,
lars has an optional argument
pred which indicates the type of data pre-processing to perform. The name of the setter method for
pred is
nagcpp:g02::OptionalG02MA::pred and it takes a single
int argument. The name of the getter method associated with an optional argument is similar to the setter method, just prepended by ‘get_’, so the getter for
pred is
nagcpp:g02::OptionalG02MA::get_pred. The getter methods take no arguments and return the value of the optional argument.
In some cases the default value for a particular argument is independent of the value of any other function argument, for example,
tol in
prob_students_t_noncentral has a default values of
. In these instances the default value can be queried as soon as the optional argument class is instantiated. In other cases the default value depends on one more input arguments, see for example
maxit in
lars whose default value depends on
mtype. In these instances the default can only be queried after the associated function has been run.
5
Error Handling
Error handling is done through the
ErrorHandler class. The behaviour of
ErrorHandler can be controlled at a global level through
GLOBAL_ERROR_HANDLER_CONTROL or on a function by function basis through the instance of
ErrorHandler stored in the optional argument class (see
Section 4).
See
Section 10 in
lars for an example of using the optional argument class to check for warnings issued by a function.
Irrespective of whether the issuing of a warning causes an exception to be thrown or not, when a warning is issued all output (and input/output) arguments will be populated as documented. In the case of a non-void function, if the issuing of a warning causes an exception to be thrown, then the return value can be obtained via
return_value.
Irrespective of whether the issuing of an error causes an exception to be thrown or not, when an error is issued the state of any output (and input/output) arguments are undefined, unless stated otherwise in the individual function documentation.
Within the NAG CPP Interface file
input/output is done through the
IOManager class which is used to translate between
std::istream or
std::ostream and the
input/output unit numbers used in the algorithmic engine.