Optimization scripts are use to run a series of simulations iteratively and check whether the process should stop after each iteration. The process is controlled using a objective function that compares the results of the simulations against observed values stored in the database.

An optimization script is similar to a simulation plan but has some additional features. The aim is to

- generate the sequence of simulations that will be carried out
- define the criteria for stopping the process

An optimization script is able to

- combine parallel (independent) simulations with sequential simulations
- calculate the parameters for the simulations during the process using the results of the previous simulations

`getNecessaryResult()`

returns all the results that are required by the optimization script and must be calculated by each simulation`getDescription()`

returns a description of the script to be displayed in the user interface`init(OptimizationContext)`

called once only, before the optimization process starts, to initialize the script`firstSimulation(OptimizationContext)`

called once only, at the start of the process, to set up the first generation of simulations`nextSimulation(OptimizationContext)`

called to set up each subsequent generation of simulations`endSimulation(OptimizationContext)`

called after each generation of simulations has completed`finish(OptimizationContext context)`

called once only, at the end of the process, when the last generation has completed

A generation of simulations is a set of independent simulations that is run for each iteration of the optimization process. All the simulations in a generation are set up at the same time using the results from the previous generations.

All the simulations in a generation may be executed in parallel – the generations are executed sequentially.

The `OptimizationContext`

is an object that is passed to each working method in the optimization script.

- It holds information on the progress of the script
- It is used to add a simulation to the current generation

Methods

`context.getCurrentGeneration()`

returns the current generation number – when the`firstSimulation()`

method is called this is 0; it will be 3 on the third call to`nextSimulation()`

`context.newSimulation()`

adds a simulation to the current generation and returns a (reference to a)`SimulationStorage`

object that can be modified by the script before the simulation is run`context.getLastSimulations()`

returns a list of SimulationStorage objects from the last generation run – results of the last generation of simulations can be extracted from these objects

A optimization script will stop when there are no more simulations to be run. If the
`nextSimulation(OptimizationContext)`

method does not call `context.newSimulation()`

then the optimization process
will stop.

An objective function is defined in an objective function script and is used to calculate a characteristic value after each simulation. There is no generic function – it is specific to each optimization problem. For example, for calibrating the model, the objective function represents the distance between the simulation results and a set of measurements.

An objective function script has the standard methods found in other scripts

`init()`

called once only, to initialize the objective function`getNecessaryResult()`

returns all the results that are required by the objective function`getDescription()`

returns a description of the objective function to be displayed in the user interface

In addition it has one particular method:

```
double eval(OptimizationContext context, List<MatrixND> exports, List<MatrixND> observations)
```

which calculates the objective function.

The three parameters are

- the simulation context
- the results from the simulation
- the observed values defined at the start of the optimization process

The objective function will usually compare the results of the simulation against the observed values and return a
`double`

indicator that will be used by the optimization script.

The value returned by the objective function script is stored in a `SimulationStorage`

object and can be recovered
using `SimulationStorage.getObjective()`

.

Objective function script `Objective3Iteration.java`

This objective function is very simple – it returns 0 until after iteration 3, (the fourth iteration), when it returns -1.:

```
public class Objective3Iteration implements Objective {
public double eval(OptimizationContext context, List<MatrixND> exports, List<MatrixND> observations) {
double result = 0;
if (context.getCurrentGeneration() >= 3) {
result = -1;
}
return result;
}
}
```

Optimization script `ExampleObjectif.java`

This optimization script sets up generations with two simulations until the objective function returns `-1`

.:

```
public class ExampleOptimization implements Optimization {
protected boolean stopped = false;
public void firstSimulation(OptimizationContext context) throws Exception {
for (int i = 0; i <= 2; i++) {
SimulationStorage storage = context.newSimulation();
// modify simulation storage
}
}
public void nextSimulation(OptimizationContext context) throws Exception {
if (!stopped) {
for (int i = 0; i <= 2; i++) {
SimulationStorage storage = context.newSimulation();
// modify simulation storage
}
}
}
public void endSimulation(OptimizationContext context) throws Exception {
List<SimulationStorage> lastGeneration = context.getLastSimulations();
for (SimulationStorage simulation : lastGeneration) {
double objective = simulation.getObjective();
if (objective <= -1) {
stopped = true;
}
}
}
}
```

This optimization script and objective function script will run 8 simulations (4 generations each with 2 simulations).