Optimisation

Les scripts d'optimisation servent à lancer plusieurs séries de simulation et évaluant à chaque itération si le script doit continuer. Cette condition est vérifiée par une fonction d'objectif qui analyse les exports habituels des simulations par rapport aux observations renseignées dans la base de données.

Script d'optimisation

Un script d'optimisation est relativement similaire à un plan d'analyse, mais il comprend quelques méthodes en plus. Son but est de générer un ensemble de simulation à être executée et déterminer une condition à l'arrêt du script.

Voici l'ensemble des méthodes présentes dans le script:
  • getNecessaryResult() : retourne l'ensemble des résultats devant être calculés par l'ensemble des simulations et nécessaire à l'execution du script d'optimisation
  • getDescription() : retourne une description du script à destination de l’utilisateur (affichée dans l'interface de lancement)
  • init(OptimizationContext) : sert à initialiser le script d’optimisation (appelée une fois, avant le lancement du script)
  • firstSimulation(OptimizationContext) : sert à générer la première génération de simulation (appelée une fois au lancement du script)
  • nextSimulation(OptimizationContext) : est appelée plusieurs fois, a chaque génération de simulation
  • endSimulation(OptimizationContext) : est appelée plusieurs fois, à chaque fin d’exécution d'une génération de simulation
  • finish(OptimizationContext context) : appelée une fois, à la fin du script, lorsque que l'ensemble des générations de simulation ont terminé

Génération de simulation

Dans les scripts d'optimisation, on parle de "génération de simulation" pour désigner un ensemble de simulation que le script d'optimisation génere à chaque itération.

Chaque génération comprend plusieurs simulation qui sont exécutées en parallèle. Mais les "génération de simulation" sont exécutées séquentiellement.

OptimisationContext

L'objet OptimizationContext est un objet qui est donné à chaque méthode du script d'optimisation. Il permet de:
  • connaitre l'état d'avancement du script
  • de produire de nouvelles simulation dans la génération courante
Liste des méthodes disponibles:
  • context.getCurrentGeneration() : permet de connaitre le numéro de la génération en cours. Par exemple, au 3ème appel de nextSimulation() le compteur sera égal à 3 (en prenant en compte que le compteur est égal à 0 dans la méthode firstSimulation()
  • context.newSimulation() : crée une nouvelle simulation dans la génération courante et la retourne sous forme de SimulationStorage (pour être modifiée par l'utilisateur avant son lancement)
  • context.getLastSimulations() : retourne l'ensemble des simulations exécutée dans la dernière génération. Les SimulationStorage retournés peuvent être lus pour en extraire des résultats

Condition d'arrêt

Un script d'optimisation s'arrête lorsqu'il n'y a plus de simulation à executer.

Donc, pour arrêter un script, il faut, dans la méthode nextSimulation(OptimizationContext) ne faire aucun appel à context.newSimulation().

Fonction d'objectif

Une fonction d'objectif sert à retourner un indicateur sur l'execution d'une simulation. Cette fonction d'objectif est à paramêtre à définir lors du lancement d'un script d'optimsation et peut donc être différente à chaque fois.

Structure

Un script d'optimisation à des méthodes classiques aux autres scripts:
  • init() pour initialiser la fonction d'objectif
  • getNecessaryResult() pour définir les résultats à calculer pour le fonction d'objectif
  • getDescription() pour fournir une description à l'utilisateur

Il contient surtout une seule méthode spécifique : double eval(OptimizationContext context, List<MatrixND> exports, List<MatrixND> observations).

Cette méthode prend en paramètres:
  • le contexte de simulation
  • les résultats des exports calculés par la simulation
  • les observations définis lors du lancement du script d'optimisation

Le but de la fonction d'objectif est de comparer les exports aux observations et à définir un indicateur double qui pourra être utile au script d'optimisation.

Le résultat de la fonction d'objectif est stocké dans le SimulationStorage et pourra être récupéré, à la fin de chaque génération, avec la méthode SimulationStorage#getObjective()

Exemple

Fonction d'objectif Objectif3Iteration.java. Cette fonction d'objectif est très simple. Elle retourne -1 losque que 3 générations de simulation ont été executées.

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;
  }
}

Script d'optimisation ExampleObjectif.java. Cet example génère des séries de 2 simulations, tant que la fonction d'objectif n'a pas retourné -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;
          }
      }
  }
}

Dans cette exemple, cette fonction d'optimisation aura lancé 8 simulations (4 séries de 2 simulations).