Internal Functions
Similar to procedures
The specification of a function is very similar to that of a procedure. The following items provide a summary of their similarities.
Arguments, together with their attributes, must be declared in a local declaration subnode.
The domain and range of indexed arguments can be in terms of either global or local sets.
The units of arguments can be expressed in terms of globally defined units of measurement, or in locally defined unit parameters.
Optional arguments must be scalar, and you must specify a default value.
AIMMS performs range checking on the actual arguments at runtime.
Both functions and procedures can have a
RETURN
statement.
There are differences
There are also differences between a function and a procedure, as summarized below:
Functions return a result that can be used in numerical expressions. The result can be either scalarvalued or indexed, and can have an associated unit of measurement.
Functions cannot have side effects either on global identifiers or on their arguments, i.e. every function argument is of type
Input
by definition.
Not allowed in constraints
AIMMS only allows the (possibly multidimensional) result of a function to be used in constraints if none of the function arguments are variables. Allowing function arguments to be variables, would require AIMMS to compute the Jacobian of the function with respect to its variable arguments, which is not a straightforward task. External functions in AIMMS do support variables as arguments (see also External Functions in Constraints).
Example: the CobbDouglas function
The CobbDouglas (CD) function is a scalarvalued function that is often used in economical models. It has the following form:
where
\(q\) 
is the quantity produced, 
\(c_f\) 
is the factor input \(f\), 
\(a_f\) 
is the share parameter satisfying \(a_f\geq 0\) and \(\sum_f a_f = 1\). 
In its simplest form, the declaration of the CobbDouglas function could look as follows.
Function CobbDouglas {
Arguments : (a,c);
Range : nonnegative;
Body : {
CobbDouglas := prod[f, c(f)^a(f)]
}
}
The arguments of the CobbDouglas
function must be declared in a
local declaration subnode. The following declarations describe the
arguments.
Set InputFactors {
Index : f;
}
Parameter a {
IndexDomain : f;
}
Parameter c {
IndexDomain : f;
}
Function attributes
The attributes of functions are listed in this table. Most of them are the same as those of procedures.
Attribute 
Valuetype 
See also 


argumentlist 


indexdomain 


range 


unitexpression 





statements 


comment string 
Returning the result
By providing an index domain to the function, you indicate that the
result of the function is multidimensional. Inside the function you can
use the function name with its indices as if it were a locally defined
parameter. The result of the function must be assigned to this
‘parameter’. As a consequence, the body of any function should contain
at least one assignment to itself to be useful. Note that the RETURN
statement cannot have a return value in the context of a function body.
The Range
attribute
Through the Range
attribute you can specify in which numerical, set,
element or string range the function should assume its result. If the
result of the function is numeric and multidimensional, you can specify
a range using multidimensional parameters which depend on all or only a
subset of the indices specified in the IndexDomain
of the function.
This is similar as for parameters (see also page The Range attribute).
Upon return from the function, AIMMS will verify that the function
result lies within the specified range.
The Unit attribute
Through the Unit attribute of a function you can associate a unit with the function result. AIMMS will use the unit specified here during the unit consistency check of each assignment to the result parameter within the function body, based on the units of the global identifiers and function arguments that are referenced in the assigned expression. In addition, AIMMS will use the value of the Unit attribute during unit consistency checks of all expressions that contain calls to the function at hand. You can find general information on the use of units in Units of Measurement. Unit Analysis of Procedures and Functions focusses on unit consistency checking for functions and procedures.
Example: computing the shortest distance
The procedure ComputeShortestDistance
discussed in the previous
section can also be implemented as a function ShortestDistance
,
returning an indexed result. In this case, the declaration looks as
follows.
Function ShortestDistance {
Arguments : (City, DistanceMatrix);
IndexDomain : j;
Range : nonnegative;
Comment : {
"This procedure computes the distance along the shortest path
from City to any other city j, given DistanceMatrix."
Body : {
ShortestDistance(j) := DistanceMatrix(City,j);
for ( j  not ShortestDistance(j) ) do
/*
* Compute the shortest path and the corresponding distance
* for cities j without a direct connection to City.
*/
endfor
}