Grid iterator on Rosenbrock function#

In this example, we will use the grid iterator on the Rosenbrock function. The Rosenbrock function is a well-known test function from optimization. It serves as the “computational model” for this example. The grid iterator evaluates a model based on a grid of the input space.

You can use QUEENS by writing a small Python script that you use to run QUEENS.

In this tutorial, we will follow the aforementioned approach and work with the script-based workflow. This allows you to run and interact with QUEENS directly in Jupyter notebooks.

[2]:
from queens.distributions.uniform import Uniform
from queens.drivers import Function
from example_simulator_functions.rosenbrock60 import rosenbrock60
from queens.global_settings import GlobalSettings
from queens.iterators.grid import Grid
from queens.main import run_iterator
from queens.models.simulation import Simulation
from queens.parameters.parameters import Parameters
from queens.schedulers import Local
from queens.utils.io import load_result

The following parameters define the experiment name (which output files would be named after) and output directory (where output files will be placed):

[3]:

# Global settings experiment_name = "grid_iterator_rosenbrock" output_dir = "./"

Here we define two parameters for our experiment: \(x_1\) and \(x_2\), both as a uniform distribution, and then grouped into a QUEENS Parameter container:

[4]:
#### Model setup ####
# Model parameters
x1 = Uniform(lower_bound=-2.0, upper_bound=2.0)
x2 = Uniform(lower_bound=-2.0, upper_bound=2.0)
parameters = Parameters(x1=x1, x2=x2)

In order to actually construct a model we require multiple things: - A scheduler. It manages the execution of your model on your local machine. - A driver. This object coordinates the evaluation of the forward model itself. - And finally, a QUEENS model itself:

[5]:

scheduler = Local(experiment_name) driver = Function(parameters=parameters, function=rosenbrock60) model = Simulation(scheduler, driver)

With the model set up, we now design the analysis parameters. In this case we do a linear grid design.

[6]:
grid_design = {
        "x1": {"num_grid_points": 5, "axis_type": "lin", "data_type": "FLOAT"},
        "x2": {"num_grid_points": 5, "axis_type": "lin", "data_type": "FLOAT"},
    }

We finally set up our method and run the iterator, then print our the results of the run:

[7]:

result_description ={ "write_results": True, "plot_results": False, } with GlobalSettings( experiment_name=experiment_name, output_dir=output_dir, debug=False ) as gs: # The method of the analysis is defined by the iterator type: method = Grid( grid_design=grid_design, result_description=result_description, global_settings=gs, model=model, parameters=parameters, ) #### Analysis #### run_iterator(method, gs) #### Load Results #### result_file = gs.output_dir / f"{gs.experiment_name}.pickle" results = load_result(result_file)

                                        *
                                      * | *
                                     * \|/ *
                                * * * \|O|/ * * *
                                 \o\o\o|O|o/o/o/
                                 (<><><>O<><><>)
                                  '==========='

          :'#######::'##::::'##:'########:'########:'##::: ##::'######::
          '##.... ##: ##:::: ##: ##.....:: ##.....:: ###:: ##:'##... ##:
           ##:::: ##: ##:::: ##: ##::::::: ##::::::: ####: ##: ##:::..::
           ##:::: ##: ##:::: ##: ######::: ######::: ## ## ##:. ######::
           ##:'## ##: ##:::: ##: ##...:::: ##...:::: ##. ####::..... ##:
           ##:.. ##:: ##:::: ##: ##::::::: ##::::::: ##:. ###:'##::: ##:
          : ##### ##:. #######:: ########: ########: ##::. ##:. ######::
          :.....:..:::.......:::........::........::..::::..:::......:::


           A general purpose framework for Uncertainty Quantification,
            Physics-Informed Machine Learning, Bayesian Optimization,
                    Inverse Problems and Simulation Analytics


+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|                                                                                 Grid                                                                                  |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| self               : <queens.iterators.grid.Grid object at 0x7ff642b813d0>                                                                                            |
| model              : <queens.models.simulation.Simulation object at 0x7ff640dc8a50>                                                                                   |
| parameters         : <queens.parameters.parameters.Parameters object at 0x7ff642d3ab90>                                                                               |
| global_settings    : <queens.global_settings.GlobalSettings object at 0x7ff640d92e50>                                                                                 |
| result_description : {'write_results': True, 'plot_results': False}                                                                                                   |
| grid_design        : {'x1': {'num_grid_points': 5, 'axis_type': 'lin', 'data_type': 'FLOAT'}, 'x2': {'num_grid_points': 5, 'axis_type': 'lin', 'data_type': 'FLOAT'}} |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+


+-------------------------------------------------------------------------------+
|                                git information                                |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| commit hash        : aff4b70184525af0f22355146ade6f1e9a401b3d                 |
| branch             : main                                                     |
| clean working tree : False                                                    |
+-------------------------------------------------------------------------------+

Grid for experiment: grid_iterator_rosenbrock

Starting Analysis...

  4%|▍         | 1/25 [00:00<00:06,  3.88it/s]

+-------------------------------------------------------------------------------+
|                         Batch summary for jobs 0 - 24                         |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs                : 25                                            |
| number of parallel jobs       : 1                                             |
| number of procs               : 1                                             |
| total elapsed time            : 3.340e-01s                                    |
| average time per parallel job : 1.336e-02s                                    |
+-------------------------------------------------------------------------------+

100%|██████████| 25/25 [00:00<00:00, 74.70it/s]

Time for CALCULATION: 0.3507523536682129 s


QUEENS output#

QUEENS output is written to a file called <experiment_name>.pickle in the directory defined by the argument output_dir of the global settings object.
There also the experiment_name has to be set. In the output folder, you also get a log file that contains the console output. It is called <experiment_name>.log.
For this example, the experiment name is set to grid_iterator_rosenbrock.
Therefore, the output can be found in the following directory: <output_dir>/grid_iterator_rosenbrock.pickle

In the case of the grid iterator, you get a dictionary including the raw input-output data and some statistics.

[8]:
results
[8]:
{'mean': array([883.]),
 'var': array([1187594.58333333]),
 'raw_output_data': {'result': array([[3.609e+03],
         [9.040e+02],
         [4.010e+02],
         [9.000e+02],
         [3.601e+03],
         [2.509e+03],
         [4.040e+02],
         [1.010e+02],
         [4.000e+02],
         [2.501e+03],
         [1.609e+03],
         [1.040e+02],
         [1.000e+00],
         [1.000e+02],
         [1.601e+03],
         [9.090e+02],
         [4.000e+00],
         [1.010e+02],
         [0.000e+00],
         [9.010e+02],
         [4.090e+02],
         [1.040e+02],
         [4.010e+02],
         [1.000e+02],
         [4.010e+02]]),
  'gradient': array([None, None, None, None, None, None, None, None, None, None, None,
         None, None, None, None, None, None, None, None, None, None, None,
         None, None, None], dtype=object)},
 'input_data': array([[-2., -2.],
        [-1., -2.],
        [ 0., -2.],
        [ 1., -2.],
        [ 2., -2.],
        [-2., -1.],
        [-1., -1.],
        [ 0., -1.],
        [ 1., -1.],
        [ 2., -1.],
        [-2.,  0.],
        [-1.,  0.],
        [ 0.,  0.],
        [ 1.,  0.],
        [ 2.,  0.],
        [-2.,  1.],
        [-1.,  1.],
        [ 0.,  1.],
        [ 1.,  1.],
        [ 2.,  1.],
        [-2.,  2.],
        [-1.,  2.],
        [ 0.,  2.],
        [ 1.,  2.],
        [ 2.,  2.]])}

Postprocessing#

You can now interact with these results as with any other Python object. For example, you can plot the results:

[9]:
import plotly.graph_objects as go
import numpy as np

input_data = results["input_data"]
output_data = results["raw_output_data"]["result"]

x = np.unique(input_data[:,0])
y = np.unique(input_data[:,1])

shape_x = x.shape[0]
shape_y = y.shape[0]

z = output_data.reshape((shape_x, shape_y))
fig = go.Figure(data=[go.Surface(x=x,y=y, z=z)])

fig.show()

Time for some individualization#

  1. The resolution of the grid is relatively coarse. Increase the resolution by increasing the num_grid_points and repeat the simulation.

  2. You can adjust the bounds of the grid per variable via the keywords: lower_bound and upper_bound.
    Go ahead and see what happens if you change the bound.
  3. Since we are evaluating a Python function we are using the Function Driver. Moreover, we are executing the study on our local machine, so we are using the Local Scheduler. You can also run the model evaluations in parallel by adjusting its num_jobs and num_procs parameters.