Grid sampling#

Description#

This example shows how to perform a grid sampling parameter scan using a GridSamplingGenerator and a TemplateEvaluator.

The template simulation script evaluates a simple function of two parameters \(x_0\) and \(x_1\):

\[f(x_0, x_1) = -(x_0 + 10 \cos(x_0)) (x_1 + 5\cos(x_1))\]

and stores the outcome in a text file result.txt. The analysis_func simply reads the value in this file.

You can adapt this example to your needs by replacing this basic template with an actual simulation and writing the corresponding analysis function. See see Running simulations for more details.

The GridSamplingGenerator generates a uniform multidimensional grid of samples to evaluate. The grid extends from the lower to the upper bound of each VaryingParameter and is divided in n_steps steps. In this case, where \(l_b=0\) and \(u_b=15\), the grid of sample looks like:

../_images/ps_grid_sampling-1.png

Scripts#

The two files needed to run this example should be located in the same folder (named e.g., example):

example
├── run_example.py
└── template_simulation_script.py

The example is executed by running

python run_example.py
run_example.py (download)#
"""Basic example of parallel grid sampling with simulations."""

from gest_api.vocs import VOCS
from optimas.generators import GridSamplingGenerator
from optimas.evaluators import TemplateEvaluator
from optimas.explorations import Exploration


def analyze_simulation(simulation_directory, output_params):
    """Analyze the simulation output.

    This method analyzes the output generated by the simulation to
    obtain the value of the optimization objective and other observables.
    The value of these parameters has to be given to the
    `output_params` dictionary.

    Parameters
    ----------
    simulation_directory : str
        Path to the simulation folder where the output was generated.
    output_params : dict
        Dictionary where the value of the objectives and observables
        will be stored. There is one entry per parameter, where the key
        is the name of the parameter given by the user.

    Returns
    -------
    dict
        The `output_params` dictionary with the results from the analysis.

    """
    # Read back result from file
    with open("result.txt") as f:
        result = float(f.read())
    # Fill in output parameters.
    output_params["f"] = result
    return output_params


# Create VOCS object defining variables, objectives.
vocs = VOCS(
    variables={
        "x0": [0.0, 15.0],
        "x1": [0.0, 15.0],
    },
    objectives={"f": "MAXIMIZE"},
)


# Create generator.
gen = GridSamplingGenerator(vocs=vocs, n_steps=[5, 7])


# Create evaluator.
ev = TemplateEvaluator(
    sim_template="template_simulation_script.py",
    analysis_func=analyze_simulation,
)


# Create exploration.
exp = Exploration(
    generator=gen, evaluator=ev, max_evals=10, sim_workers=4, run_async=True
)


# To safely perform exploration, run it in the block below (this is needed
# for some flavours of multiprocessing, namely spawn and forkserver)
if __name__ == "__main__":
    exp.run()
template_simulation_script.py (download)#
"""Simple template script used for demonstration.

The script evaluates an analytical expression and stores the results in a
`result.txt` file that is later read by the analysis function.
"""

import numpy as np

# 2D function with multiple minima
result = -({{x0}} + 10 * np.cos({{x0}})) * ({{x1}} + 5 * np.cos({{x1}}))

with open("result.txt", "w") as f:
    f.write("%f" % result)