Example

In this section we will go through the setup and running of a simple everest optimization case.

Problem definition

The optimization problem we will solve using everest will be to minimize the distance between an initial 3D point and another given target 3D point.

Everest config

The main element an Everest optimization experiment requires is a configuration file. Everest supports the YAML format for the configuration file. The configuration file is build up of multiple sections and next we will go through it section by section.

Creating the optimization folder:

~$: mkdir everest_example
~$: cd everest_example
~/everest_example$: touch everest_config.yml

Controls definition

everest_config.yml:

controls:
  -
    name: point
    type: generic_control
    min: -1.0
    max: 1.0
    initial_guess: 0
    perturbation_magnitude : 0.001
    variables:
        - name: x
        - name: y
        - name: z

Details

name: control defined name

min: minimal value each of the control variables can take

max: maximal value each of the control variables can take

initial_guess: the initial value for the control variables

min, max and initial_guess can also be defined for each control individually:

controls:
  -
    name: point
    type: generic_control
    initial_guess: 0
    perturbation_magnitude : 0.001
    variables:
      -
        name: x
        initial_guess: 0
        min: -1.0
        max: 1.0
      -
        name: y
        initial_guess: 0
        min: -1.0
        max: 1.0
      -
        name: z
        initial_guess: 0
        min: -1.0
        max: 1.0

perturbation_magnitude controls the size of perturbations (standard deviation of a normal distribution) of controls used to approximate the gradient. The value depends on the type of control and magnitude of the variables. For continuous controls smaller values should give a better gradient, whilst for more discrete controls larger values should give a better result. However, this is a balance as too large or too small values also cause issues.

variables: list of control variables.

Objective function definition

everest_config.yml:

objective_functions:
  -
    name: distance

Optimization definition

everest_config.yml:

optimization:
  algorithm: optpp_q_newton
  convergence_tolerance: 0.005

Details

algorithm: the algorithm used for the optimization currently supported algorithms: optpp_q_newton, conmin_mfd, conmin_frcg, mesh_adaptive_search.

convergence_tolerance: provides a real value for controlling the termination of iteration. In most cases, it is a relative convergence tolerance for the objective function; i.e., if the change in the objective function between successive iterations divided by the previous objective function is less than the amount specified by convergence_tolerance, then this convergence criterion is satisfied on the current iteration. Since no progress may be made on one iteration followed by significant progress on a subsequent iteration, some libraries require that the convergence tolerance be satisfied on two or more consecutive iterations prior to termination of iteration (from the Dakota Manual.)

Install jobs definition

everest_config.yml:

install_jobs:
  -
    name: distance3d
    executable: jobs/distance3d.py

Details

The custom job can be installed by adding information regarding it in the install_jobs section. Each custom job entry will contain:

name: the name the job, the same name will be used in the forward model section.

executable: the file path to the job’s executable.

Model definition

everest_config.yml:

model:
  realizations: [0]

Details

realizations: list of realizations to use in optimization ensemble. Typically, this is a list [0, 1, …, n-1] of all realizations in the ensemble.

Forward model definition

everest_config.yml:

forward_model:
  - distance3d --point-file point.json --target 0.5 0.5 0.5 --out distance

Details

distance3d: the name of the custom job installed in the install_jobs section of the config file. The job name is followed by named arguments the job is designed to accept.

point.json: file generated by the Everest optimization experiment. It contains the list of control variables with the values used for the current forward model evaluation.

Example:

{
"x" : 0,
"y" : 0,
"z" : 0
}

Everest creates the file with the name point.json because we have added to the controls section the control with the name point.

distance: file required for the optimization experiment to succeed.

One of the jobs in the forward model needs to create the file distance.

distance needs to contain the value for the objective function evaluation.

The files needs to be called distance because we have defined the objective function named distance.

Optimization environment definition

everest_config.yml:

environment:
  simulation_folder: sim_output
  output_folder: everest_optimization
  random_seed: 999

Details

simulation_folder: folder path where the simulation information will be written to.

output_folder: folder path where the optimization information will be written.

random_seed: integer used to make optimization experiments reproducible

Putting all together

everest_config.yml:

controls:
  -
    name: point
    type: generic_control
    min: -1.0
    max: 1.0
    initial_guess: 0
    perturbation_magnitude : 0.001
    variables:
        - name: x
        - name: y
        - name: z

objective_functions:
  -
    name: distance

optimization:
  algorithm: optpp_q_newton
  convergence_tolerance: 0.005

install_jobs:
  -
    name: distance3d
    executable: jobs/distance3.py

model:
  realizations: [0]

forward_model:
  - distance3d --point-file point.json
              --target 0.5 0.5 0.5
              --out distance

environment:
  simulation_folder: sim_output
  output_folder: everest_optimization
  random_seed: 999

More information regarding all the available section options and additional sections not covered in the current example can be found in Everest configuration section

Creating the custom job

Before we are able to start the optimization experiment we need to create the script for the custom job distance3d used in the forward model.

Creating the folders and files:

~/everest_example$: mkdir jobs
~/everest_example$: cd jobs
~/everest_example/jobs$: touch distance3d.py
~/everest_example/jobs$: chmod a+x distance3d.py

chmod +x distance3d.py: command is used to change the access permissions for the file distance3d.py, such that execution of the file is allowed.

distance3d.py:

#!/usr/bin/env python

import argparse
import json
import sys


def compute_distance_squared(p, q):
    d = ((i - j) ** 2 for i, j in zip(p, q))
    d = sum(d)
    return -d

def read_point(filename):
    with open(filename, "r") as f:
        point = json.load(f)
    return point["x"], point["y"], point["z"]

def main(argv):
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument("--point-file", type=str)
    arg_parser.add_argument("--point", nargs=3, type=float)
    arg_parser.add_argument("--target-file", type=str)
    arg_parser.add_argument("--target", nargs=3, type=float)
    arg_parser.add_argument("--out", type=str)
    options, _ = arg_parser.parse_known_args(args=argv)

    point = options.point if options.point else read_point(options.point_file)
    if len(point) != 3:
        raise RuntimeError("Failed parsing point")

    target = options.target if options.target else read_point(options.target_file)
    if len(target) != 3:
        raise RuntimeError("Failed parsing target")

    value = compute_distance_squared(point, target)

    if options.out:
        with open(options.out, "w") as f:
            f.write("%g \n" % value)
    else:
        print(value)

if __name__ == "__main__":
    main(sys.argv[1:])

More information about creating custom jobs can be found in the Custom forward model jobs section

Running everest

Now we have all the components needed to start the optimization experiment, which can be done using the following command:

~/everest_example$: everest run everest_config.yml

A successful run should provide the following information in the console:

===================================    Optimization progress     ===================================
objective_history
  [-0.75, -0.741387, -3.0771e-06, -3.52973e-05, -1.9738e-06]
control_history
  point_x
    [0.0, 0.9969848491048954, 0.5004497377256543, 0.494934760761201, 0.4987474020091786]
  point_y
    [0.0, 0.9969449712812354, 0.4983102069271145, 0.5024668256000643, 0.49959325134821364]
  point_z
    [0.0, 0.9974323304790726, 0.4998643423913659, 0.5018857127965773, 0.5004882889752225]
objectives_history
  distance
    [-0.75, -0.741387, -3.0771e-06, -3.52973e-05, -1.9738e-06]
accepted_control_indices
  [0, 1, 2, 4]
All 1 active jobs complete and data loaded.