Introduction
Getting started
The aim of this section is to give you a quick feel for the effort
required to make a link to an external function or procedure through a
short illustrative example linking a C
implementation of the
Cobb-Douglas function (discussed in Example: the Cobb-Douglas function) into an
AIMMS application. Introduction contains a more elaborate
example of an external procedure which uses AIMMS API functions to
obtain additional information about the passed arguments.
External procedures and functions
The interface to external procedures and functions is arranged through
special ExternalProcedure
and ExternalFunction
declarations
which behave just like internal procedures and functions. Instead of
specifying a body to initiate internal AIMMS computations, the execution
of external procedures and functions is relayed to the indicated
procedures and functions inside one or more DLL’s.
The Cobb-Douglas function
Consider the Cobb-Douglas
function discussed in
Example: the Cobb-Douglas function. Given the cardinality n
of the set
InputFactors
and two arrays a
and c
of doubles representing
the one-dimensional input arguments of the Cobb-Douglas function (both
defined over InputFactors
), the following simple C
function
computes its value.
double Cobb_Douglas( int n, double *a, double *c ) {
int i;
double CD = 1.0 ;
for ( i = 0; i < n; i++ )
CD = CD * pow(c[i],a[i]) ;
return CD;
}
In the sequel it is assumed that this function is contained in a DLL
named "Userfunc.dll"
.
Linking to AIMMS
In order to make the function available in AIMMS you have to declare an
ExternalFunction
CobbDouglasExternal
, which just relays its
execution to the C
implementation of the Cobb-Douglas function
discussed above. The declaration of CobbDouglasExternal
looks as
follows.
ExternalFunction CobbDouglasExternal {
Arguments : (a,c);
Range : nonnegative;
DLLName : "Userfunc.dll";
ReturnType : double;
BodyCall : Cobb_Douglas( card : InputFactors, array: a, array: c );
}
The arguments a
and c
must be declared in the same way as for
the internal CobbDouglas
function discussed on
Example: the Cobb-Douglas function, with the exception that for the external
implementation we will also compute the Jacobian with respect to the
argument c(f)
. For this reason, the argument c(f)
is declared as
a Variable
.
Set InputFactors {
Index : f;
}
Parameter a {
IndexDomain : f;
}
Variable c {
IndexDomain : f;
}
Explanation
The translation type card
of the set argument InputFactors
causes AIMMS to pass the cardinality of the set as an integer value to
the external function Cobb_Douglas
. The translation type array
of the arguments a
and c
are instructions to AIMMS to pass these
arguments as full arrays of double precision values. As function
arguments are always of type Input
, AIMMS will disregard any changes
made to the arguments by the external function. The double
return
value of the C
function Cobb_Douglas
will become the result of
the function CobbDouglasExternal
.
Calling external functions
After the declaration of an external function or procedure you can use
it as if it were an internal function or procedure. Thus, to call the
external function CobbDouglasExternal
in the body of a procedure the
following statement suffices.
CobbDouglasValue := CobbDouglasExternal(a,c) ;
Of course, any two (possibly sliced) identifiers with single common index domain could have been used as arguments. AIMMS will determine this common index domain, and pass its cardinality to the external function.
Use in constraints
Unlike internal functions, external functions can be called inside
constraints. To accomplish this, the declaration has to be extended with
a DerivativeCall
attribute. For this attribute you specify the
external call that has to be made when AIMMS also needs the partial
derivatives of all variable arguments inside constraints of mathematical
programs. In the absence of a DerivativeCall
attribute, AIMMS will
use a differencing scheme to estimate these derivatives. The details of
using external functions in constraints, as well as the obvious
extension to compute the derivative of the Cobb-Douglas function
directly, are given in External Functions in Constraints.
Setting up external libraries
Once you have developed a collection of external functions and procedures, it may be a good idea to make this available in the form of a library for use in AIMMS applications. In this way, the users of your library do not have to spend any time translating their AIMMS arguments into external arguments of the appropriate type in the external procedure and function declarations.
Save library as include file
To provide a library as an entity on its own, you can store all the external procedures and functions in a separate model section, and save this section as a source file. The functions and procedures in the library can then be made available by simply including this source file into a model.
Hiding the interface
When you want to protect the interface to your external library, you can accomplish this by encrypting the include file containing the function library. Thus, the interface to the external library becomes invisible, effectively preventing misuse of the library outside AIMMS.