2. 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 0x7f922e17d4d0> |
| model : <queens.models.simulation.Simulation object at 0x7f922fd9dc10> |
| parameters : <queens.parameters.parameters.Parameters object at 0x7f922fcf0d90> |
| global_settings : <queens.global_settings.GlobalSettings object at 0x7f922dfa2bd0> |
| 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 : 568a363c0509d024098bbb97b04e15f7925ed711 |
| branch : main |
| clean working tree : False |
+-------------------------------------------------------------------------------+
Grid for experiment: grid_iterator_rosenbrock
Starting Analysis...
4%|▍ | 1/25 [00:00<00:06, 3.82it/s]
+-------------------------------------------------------------------------------+
| Batch summary for jobs 0 - 24 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 25 |
| number of parallel jobs : 1 |
| number of procs : 1 |
| total elapsed time : 3.384e-01s |
| average time per parallel job : 1.354e-02s |
+-------------------------------------------------------------------------------+
100%|██████████| 25/25 [00:00<00:00, 73.71it/s]
Time for CALCULATION: 0.35550355911254883 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.pickleIn 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_pointsand repeat the simulation.- You can adjust the bounds of the grid per variable via the keywords:
lower_boundandupper_bound.Go ahead and see what happens if you change the bound. Since we are evaluating a Python function we are using the
FunctionDriver. Moreover, we are executing the study on our local machine, so we are using theLocalScheduler. You can also run the model evaluations in parallel by adjusting itsnum_jobsandnum_procsparameters.