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#
<experiment_name>.pickle
in the directory defined by the argument output_dir
of the global settings object.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
.grid_iterator_rosenbrock
.<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#
The resolution of the grid is relatively coarse. Increase the resolution by increasing the
num_grid_points
and repeat the simulation.- You can adjust the bounds of the grid per variable via the keywords:
lower_bound
andupper_bound
.Go ahead and see what happens if you change the bound. 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 theLocal
Scheduler. You can also run the model evaluations in parallel by adjusting itsnum_jobs
andnum_procs
parameters.