User function (general form)


Purpose
The general form of the user function includes possibilities for calculating and returning an array of values, including partial derivatives if appropriate. Additional features include optional information about the calling program.
Synopsis
function fName (aName:array(aRange:range) of real,
 nName:array(nRange:range) of integer
 [,iName:array(iRange:range) of string]
 [,oName:array(oRange:range) of string]
 [,dName:array(dRange:range) of string]
 [,rName:array(rRange:range) of  real]) : real

Arguments
aName 
an array of type real containing the actual values of the parameters to the function
nName 
an array of type integer containing the function information array
iName 
an array of type string containing the array of input names
oName 
an array of type string containing the array of output names
dName 
an array of type real containing the array of partial derivative flags
rName 
an array of type real to contain the array of results from the function
Example
The following is an example of a general Mosel user function which calculates the product of a set of numbers and also the partial derivatives with respect to each of them. It takes four parameters: the input values, the function information array, the array of partial derivative flags, and an array to hold the return values. The function itself returns zero for success (and would return nonzero for failure).
function Product(Values:array(vRange:range) of real,
                 FuncInfo:array(fRange:range) of integer,
                 Deltas:array(dRange:range) of real,
                 Return:array(rRange:range) of real) :real
  nValue := FuncInfo(fRange(1))
  declarations
    Value: real
    Derivatives: array(1..nValue) of real
  end-declarations
  Value := 1
  forall (i in 1..nValue) Derivatives(i) := 1
  forall (i in 1..nValue) do
    Value := Value * Values(vRange(i))
    forall (j in 1..nValue | j <> i) 
      Derivatives(j) := Derivatives(j)* Values(vRange(i))
  end-do

  Return(rRange(1)) := Value
  j := 1
  forall (i in 1..nValue) do
    if Deltas(dRange(i)) <> 0 then
      j += 1
      Return(rRange(j)) := Derivatives(i)
    end-if
  end-do
  returned := 0
end-function

The number of input values is given in the first item in the FuncInfo array. For ease of explanation in this case, the partial derivatives are calculated for all the input variables (that is, for each item in the Values array). Deltas(i) is zero if a derivative is not required for the ith item, and nonzero if a derivative is required. This is tested in the final loop, when the Derivatives array is packed into the Return array.

The function is declared by using the SLPDATA("UF") procedure and can then be called using the Func wrapper as in the following example:

declarations
 X,Y: mpvar
 Values, Deltas, Results: array(1..100) of real
 FuncInfo: array(1..xslp_funcinfosize) of integer
 NullStr:dynamic array(1..1) of string
 XArray:array(1..6) of string
end-declarations
 XArray := ["Values","FuncInfo","NullStr",
            "NullStr","Deltas","Results"]
 SLPDATA("UF","Product","",
    "DOUBLE,INTEGER,,,DOUBLE,DOUBLE",
    "Mosel","Model","XArray")
 Func("Product",X,Y) <= 10

The presence of the Deltas argument in the function definition defines the function as calculating its own derivatives. There is no change in the way the function is written in constraints, and the system will decide when derivatives are required.

Further information

The order and purpose of the arguments to a Mosel user function follow the standard layout for Xpress-SLP user functions as described in the Xpress-SLP reference manual.

aName
The actual values of the parameters to the function are passed in the array aName
nName
This holds various information items about the function and its arguments. In particular:
nName(1)
is the number of parameters (the actual number of values in the array aName)
nName(2)
is the number of return values required. This is only important if the function returns multiple values and the actual number or order required may vary
nName(3)
is the number of sets of partial derivatives required. If the function is declared as providing its own derivatives, then nName(3) is the number required on this call to the function, which may be zero
iName
This is an optional argument, which is used if the function receives values by name rather than by position. If it is used, then the names of the arguments are provided in the same order as the values
oName
This is an optional argument, which is used if the function returns multiple values by name rather than by position. If it is used, then the names of the values are provided in the order in which the values are required
dName
This argument is only used when the function is declared as providing its own partial derivatives. If it is used, it will have one entry for each item in aName. The value in dName is nonzero if a partial derivative is required for the corresponding item in aName, and zero otherwise. A nonzero value can be used as a basis for numerical derivatives if required. The number of nonzero entries in dName is in nName(3)
rName
This argument is normally used when the function returns multiple values, either because it is a multi-valued function, or because it calculates its own derivatives.
On return, rName must contain the required values. The return value must be 0 if the function has completed successfully, or a positive value (Maths/geq.png1) if it failed.


If you have any comments or suggestions about these pages, please send mail to docs@dashoptimization.com.