Working with submodels : Multiple-instance submodels : Fixed

Multiple-instance submodels: fixed membership

A fixed-membership submodel is one type of multiple-instance submodel. In this case, the number of instances is fixed throughout the simulation run.

By making a fixed-membership multiple-instance submodel, we are saying that:

  • The model contains a fixed number of objects, each of which behaves according to the same rules (represented by the model elements and equations inside it).
  • Each object may (and usually does) differ in one or more numeric values: the initial value for compartments, or the values of parameters.

When should I use a fixed-membership multiple-instance submodel?

Fixed-membership submodels are useful for handling many forms of disaggregation in model design. You may, for example, be interested in modelling the changing population of a country like the UK. You first model has a single compartment, representing the total population size. You then decide to represent this information on a regional basis, in order to capture differences in population parameters in different regions. You have now disaggregated your model into multiple regions. Your model diagram looks very similar: the only difference is that the part representing population dynamics is now wrapped up in a multiple-instance submodel, one instance for each region. This is a fixed membership submodel, because the number of regions is fixed.

Conversely, fixed-membership models can be used for scaling up. To take the previous context, you might have begun making a model of the population growth of just one region. You then want to scale the model up to the whole of the UK. Again, you wrap up the original model and make it into a fixed-membership, multiple-instance submodel.

Although disaggregation and scaling up are conceptually very different - in fact, opposite - activities, the appearance of both the before and after model diagrams is the same in both cases. The only difference comes in terms of the initialisation and parameterisation for the original model.

How to make a fixed-membership submodel

  1. Use the submodel tool to drag a submodel envelope on your model diagram. The submodel may be drawn in an open area of the model diagram, and not enclose anything. Or you can drag the submodel around existing elements on your model diagram, if you want those enclosed in the submodel.
  1. Open up the submodel properties dialogue by selecting the Pointer tool, then double-clicking anywhere in the blank area of the submodel (not on its border, and not on any existing elements). Note that the "Generated set" radio button has been selected by default. This term denotes that the submodel is to be fixed-membership. Enter a value into the "Dimensions" box corresponding to the number of instances you want. Click on the "OK" button.
  1. Back on the model diagram, the submodel's appearance has now changed. Its simple border has now been replaced by multiple lines on the bottom and right, indicating that there is a fixed number of multiple instances (it's meant to look like a stack of cards).

Dimensions of a fixed-membership submodel

The dimensions of a submodel are a list of one or more dimensions, separated by commas if there is more than one. Each dimension can be:

  • An integer greater than 1, or
  • The name of an enumerated type, or
  • size(x), where x is the name of another component in the model. The dimension then has the same value as the dimensions of the named component.

If there is just one dimension, the submodel's instances form a one-dimensional array, or vector, in which each instance has a unique index which is a number starting from one (if the dimension is numerical) or a member of the enumerated type whose name is the dimension.

If there is more than one dimension, the submodel instances are arranged in an n-dimensional array, with each instance having indices corresponding to its place long each dimension.

How to make the different instances different

There are two main ways in which you can make one instance different from the others.

  • You can give each instance a different initial value for one or more compartments.
  • You can give each instance a different value for one or more parameters.

Conceptually, these are very different. In the first case, you are saying that the differences between the individuals are simply in terms of the state they happen to be in when you start the simulation. In the second case, you are saying that the individuals differ in some intrinsic property. You can of course mix these: individuals may differ in both their initial state and their parameterisation.

There are several methods you can use to assign different values to different instances. These techniques apply equally to compartments and parameters.

Load the values from a file

If you put a fixed parameter inside a fixed membership submodel, then when you run the model, there will be an entry in the file parameters dialogue requiring values for this parameter. The data you enter will have to include a value for each instance of the submodel.

Generate the values randomly

Enter the expression

rand_const(0,10) (replacing 0 and 10 by whatever range you want)

in the Equation box for the compartment or parameter to cause each instance to be assigned a value randomly picked from the specified range. rand_const(A,B) samples from a rectangular probability distribution over the range A...B: Simile also alows you to use values from other distributions, e.g. Normal (and it is possible to engineer these yourselves).

Note that if there is no explicit indication that they return a constant value, Simile's statistical functions return a new sample from the given distribution on each time step. If you are using a sampling function to set up a multiple instance submodel with data that conforms to a statistical pattern, it is probable that you want each instance to keep the value it was given when the model was initialized or reset. This can be arranged by wrapping the statistical function in the at_init() function, e.g., at_init(gaussian_var(50,10)).

Select elements from an array

If your submodel has a small number of instances, you can explicitly list the value for each instance in an array, and select from this array the value for each instance.

Let's say you want to model the loss of water from 5 tanks. The tanks differ in terms of the initial amount of water they hold: say 10,5,20,50 and 9 litres. You have made the water flow model into a submodel with 5 instances. You could use the following expression in the Equation box to initialise the water compartment:

element([10,5,20,50,9],index(1)) (replacing [10,…,9] by whatever you need)

This selects the value 10 for the first instance, the value 5 for the second, and so on. See the help information on the functions element and index for more information.

Alternatively, you could have a separate array variable, say "initial_water", whose only job is to hold the array of values, take an influence arrow from it to the compartment, then select a value from that array for each instance:

initial_water = [10,5,20,50,9]

water = element([initial_water],index(1))

Use conditional expressions

You can develop expressions conditional on the value of index(1) (i.e. the numeric index of each instance) in a wide variety of ways. For example, you want the first three instances to have a value of 20, and the rest 10, then you could use the expression:

if index(1)<=3 then 20 else 10

Use a sketched graph or built-in table

You could use the sketch graph or built-in table functions in the equation dialogue to specify the values of the compartment or parameter as a function of index(1). This is particularly appropriate if the instances have a natural ordering, e.g. age-classes in a population, or soil layers, when the quantity under consideration might be considered to have some ordered relationship with the instance number.

The in_preceding() function

This calculates the value of its argument in the immediately preceding instance of the submodel. For instance, a variable with the equation in_preceding(prev(0))+1 will have a value of 1 in the first instance, 2 in the second, and so on up to the total number of instances in the last instance, irrespective of the submodel's dimensions.

Variables exported from a fixed-membership multiple-instance submodel

If you take an influence from a variable (a) in a fixed-membership multiple-instance submodel to another variable (b) in the same submodel, then b sees a as a scalar variable: i.e. as having a single value. You could use an expression for b like

3*a

How can this be, when we know that a has one value for every instance of the submodel? It's because the equation is expressed as a general rule: whatever value of a a particular instance has, then its value of x is 3 times greater.

However, things change when we take an influence from a variable (a) in the submodel to one outside (c). Because c is outside the submodel, it can see all the values of a. a must now be treated as an array of values, not as a single value.

An array is denoted by enclosing the name of the variable with [...], thus a inside the submodel has become [a] outside it. Thus, when we open up the Equation dialogue window for c, the influencing variable appears as an array, and its name is enclosed in square brackets. And the expression for calculating c must do the same. Thus, legitimate expressions for c are:

3*[a] c becomes an array with as many elements as a, each multiplied by 3

sum([a]) c has a single value, equal to the sum of the elements in the array [a]

In: Contents >> Working with submodels