Initializing help system before first use

Programming Techniques for User Functions

This section is principally concerned with the programming of large or complicated user functions, perhaps taking a potentially large number of input values and calculating a large number of results. However, some of the issues raised are also applicable to simpler functions.

The first part describes in more detail some of the possible arguments to the function. The remainder of the section looks at function instances, function objects and direct calls to user functions.

Deltas

The Deltas array has the same dimension as InputValues and is used to indicate which of the input variables should be used to calculate derivatives. If Deltas[i] is zero, then no derivative should be returned for input variable i. If Deltas[i] is nonzero, then a derivative is required for input variable i. The value of Deltas[i] can be used as a suggested perturbation for numerical differentiation (a negative sign indicates that if a one-sided derivative is calculated, then a backward one is preferred). If derivatives are calculated analytically, or without requiring a specific perturbation, then Deltas can be interpreted simply as an array of flags indicating which derivatives are required.

Return values and ReturnArray

The ReturnArray array is provided for those user functions which return more than one value, either because they do calculate more than one result, or because they also calculate derivatives. The function must either return the address of an array which holds the values, or pass the values to the calling program through the ReturnArray array.

The total number of values returned depends on whether derivatives are being calculated. The FunctionInfo array holds details of the number of input values supplied, the number of return values required (nRet) and the number of sets derivatives required (nDeriv). The total number of values (and hence the minimum size of the array) is nRet*(nDeriv+1). Xpress NonLinear guarantees that ReturnArray will be large enough to hold the total number of values requested.

A function which calculates and returns a single value can use the ReturnArray array provided that the declarations of the function in Xpress NonLinear and in the native language both include the appropriate argument definition.

functions which use the ReturnArray array must also return a status code as their return value. Zero is the normal return value. A value of 1 or greater is an error code which will cause any formula evaluation to stop and will normally interrupt any optimization or other procedure. A value of -1 asks Xpress NonLinear to estimate the function values from the last calculation of the values and partial derivatives. This will produce an error if there is no such set of values.

Returning Derivatives

A multi-valued function which does not calculate its own derivatives will return its results as a one-dimensional array.

As already described, when derivatives are calculated as well, the order is changed, so that the required derivatives follow the value for each result. That is, the order becomes:
A,

∂A
∂X1
,
∂A
∂X2
, ...
∂A
∂Xn
, B,
∂B
∂X1
,
∂B
∂X2
, ...
∂B
∂Xn
, ...
∂Z
∂Xn

where A, B, Z are the return values, and X1, X2, Xn, are the input (independent) variables (in order) for which derivatives have been requested.

Not all calls to a user function necessarily require derivatives to be calculated. Check FunctionInfo for the number of derivatives required (it will be zero if only a value calculation is needed), and Deltas for the indications as to which independent variables are required to produce derivatives. Xpress NonLinear will not ask for, nor will it expect to receive, derivatives for function arguments which are actually constant in a particular problem. A function which provides uncalled-for derivatives will cause errors in subsequent calculations and may cause other unexpected side-effects if it stores values outside the expected boundaries of the return array.

Function Instances

Xpress NonLinear defines an instance of a user function to be a unique combination of function and arguments. For functions which return an array of values, the specific return argument is ignored when determining instances. Thus, given the following formulae:
 f(x) + f(y) + g(x,y : 1)
 f(y)*f(x)*g(x,y : 2)
 f(z)
the following instances are created:
f(x)
f(y)
f(z)
g(x,y)
(A function reference of the form g(x,y:n) means that g is a multi-valued function of x and y, and we want the nth return value.)

Xpress NonLinear regards as complicated any user function which returns more than one value, which uses input or return names, or which calculates its own derivatives. All complicated functions give rise to function instances, so that each function is called only once for each distinct combination of arguments.

Functions which are not regarded as complicated are normally called each time a value is required. A function of this type can still be made to generate instances by defining its ExeType as creating instances (set bit 9 when using the normal library functions, or use the "I" suffix when using file-based input through XSLPreadprob or when using SLPDATA in Mosel).

Note that conditional re-evaluation of the function is only possible if it generates function instances.

Using function instances can improve the performance of a problem, because the function is called only once for each combination of arguments, and is not re-evaluated if the values have not changed significantly. If the function is computationally intensive, the improvement can be significant.

There are reasons for not wanting to use function instances:

  • When the function is fast. It may be as fast to recalculate the value as to work out if evaluation is required.
  • When the function is discontinuous. Small changes are estimated by using derivatives. These behave badly across a discontinuity and so it is usually better to evaluate the derivative of a formula by using the whole formula, rather than to calculate it from estimates of the derivatives of each term.
  • Function instances do use more memory. Each instance holds a full copy of the last input and output values, and a full set of first-order derivatives. However, the only time when function instances are optional is when there is only one return value, so the extra space is not normally significant.

© 2001-2020 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.