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.