Optimization scripts

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.

Principles

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

Basic methods in an optimization script

  • 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

Generation of simulations

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.

Optimization context

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

Stopping the process

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.

Objective function

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.

Structure

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().

A simple example

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).