There are three different mechanisms for users to supply functions for use in expressions:
User-supplied function declarations and definitions should be put in files in the Functions directory in Simile's local data tree. This tree is created automatically when you first run Simile. Its location is:
Declarations and definitions in the Functions directory in Simile's installation tree (e.g., "Program files/Simile54") are for functions treated as "Built-In", i.e., expected to be available in any Simile system. It is worth looking at these for guidance in writing your own functions, as the formats are the same.
In: Contents >> Working with equations
Macro definitions provide a shorthand for long, complex expressions that would otherwise have to be used in equations, possibly in several different elements. The definitions are stored in one or more external files, which are read each time Simile starts. Users may edit the files to include user-defined macros.
Each new macro is defined in a new line in any file with the extension .pl in the Functions directory. There are two places where this directory can be; one is within the Simile program files tree (for built-in functions), and the other is under Simile's local directory (for functions to be treated as user-defined). Any functions added by modellers should be placed in the latter location; this has the effect that when a model requiring the functions is saved, they are marked as user-defined, and if the model is subsequently opened on a system where the function definitions are not present, a warning is displayed saying which user-defined functions are missing.
The format of the macro definition line is:
f(X1, X2 ... Xn) --> F(X1, X2 ... Xn).
where:
The function, as it appears on the left side of the arrow, can then be used in any Simile equation, with any sub-expression taking the place of each of the variable identifiers. The result returned by the function will be the same as that which would have been returned by the expression on the right hand side, if the same sub-expressions had been substituted for the variable identifiers.
The .pl files distributed with Simile (and installed in the Functions directory in Simile's program files) contain a number of examples of function definitions. These include the following:
Comment lines, starting with a %, can be included in this file, and standard multi-line comments bounded by /*...*/ can be used.
If there is a syntax error in a user function definition, this will cause a warning to be produced when Simile is started. The other definitions will still be usable.
In: Contents >> Working with equations >> User-defined functions
To include user-defined external procedures, there are three files:
function(Name, ResultType, ArgTypes).
This form is used for ordinary, deterministic functions.
sample(Name, ResultType, ArgTypes).
This form is used for functions which give a new value each time they are called, even if the arguments do not change. This is used for stochastic functions such as gaussian_var, and is required because Simile otherwise tries to be lazy -- it only re-evaluates a function if the arguments change.
In either form, "Name" is the name of the function, which is used in Simile's equation language. "ResultType" the type of the result - one of int, real, boolean or any - and "ArgTypes" a list of argument types in the same form. These allow the Prolog equation parser to accept this function in equations, and to put it into the target language program as a procedure call wherever it is used.
These files are stored in the Functions directory of the Simile program files tree. If you wish to build models in both C++ and Tcl, using the same function name, you must include the function definition is both procs.cpp and procs.tcl.
It is generally not a good idea to use global variables in the function definitions, because if the functions are used in more than one place in the model, a value set when running one instance of it may be used when running another instance.
In: Contents >> Working with equations >> User-defined functions
This feature, introduced in Simile v6, is really, really easy to use. Suppose you need to have a particular function available in your model, and you have no idea how to program it in c++ or write a macro expression for it, but you can easily make a simple Simile model that implements the function. One option would be to build such a model, and copy it to every part of the model you are working on where you need the function it provides. The trouble is, this would make the diagram confusing and the model would be harder to maintain, since if you changed the implementation of the function you would have to change all the occurrences of the model fragment that carries it out.
Now you can keep the model fragment somewhere else, and refer to it wherever you like by means of an ordinary function. The fragment goes in a directory called Fragments which is a subdirectory of either of the Functions directories for user-defined functions in general. The name of the function it implements, and the components of the fragment which correspond to the result and arguments, are identified by the name of the fragment file, which has the format
functor,result,arg,... .sml
For instance, suppose you want a function that returns the first prime number greater than its argument. You could make a model fragment that looks like this:
This model takes a number in the 'start' variable, and generates the next prime number up from it in the 'next' variable. It uses two nested iterative submodels. The outer one tries each odd number, starting from 'start', until one is found to be prime. The inner one applies the test for primeness, dividing the candidate by each odd number starting from 3 until either an exact factor is found, or the next divisor is greater than the square root of the candidate. If a factor is found, the outer submodel moves on to the next candidate and the inner one starts again.
So, we have our model, how do we make the function? By saving it in the Fragments directory with a name made of the following parts:
These are all separated by commas and the name finishes with the .sml extension as for any Simile model, so the full name is
next_prime,next,start.sml
Now you can use the function in any equation, e.g. "next_prime(z)>50"
In: Contents >> Working with equations >> User-defined functions