Interface for Python

The following section contains the documentation for using the Python interface that allows to set up, run studies and analyze their results.

The interface consists of the following Python classes

Class

Purpose

Server

Class for for starting and stopping the optimization server.

Client

Class for connecting to server, creating studies, and creating benchmarks.

Study

Class for configuring, running and analyzing results of a study

Observation

Container for observations to be sent to the server.

Suggestion

Suggestion retrieved by a study to be evaluated.

Driver

Interface to driver-specific methods.

Benchmark

Class for benchmarking different studies against each other

Benchmark

class jcmoptimizer.Benchmark(benchmark_id, num_average, requestor)[source]

This class provides methods for benchmarking different studies against each other that try to minimize the same objective. Example:

benchmark = client.create_benchmark(num_average=6)
benchmark.add_study(study1)
benchmark.add_study(study2)
benchmark.set_evaluator(evaluate)
benchmark.run()
data = benchmark.get_data(x_type='num_evaluations',y_type='objective',
           average_type='mean')
fig = plt.figure(figsize=(8,4))
for idx,name in enumerate(data['names']):
    X = data['X'][idx]
    Y = np.array(data['Y'][idx])
    std_error = np.array(data['sdev'][idx])/np.sqrt(6)
    p = plt.plot(X,Y,linewidth=2.0, label=name)
    plt.fill_between(X, Y-std_error, Y+std_error, alpha=0.2, color = p[0].get_color())
plt.legend(loc='upper right',ncol=1)
plt.grid()
plt.ylim([0.1,10])
plt.rc('font',family='serif')
plt.xlabel('number of iterations',fontsize=12)
plt.ylabel('average objective',fontsize=12)
plt.show()

The constructor should not be used directly since it does not create a benchmark on the server side. Instead, one should use Client.create_benchmark().

add_study

Benchmark.add_study(study)

Adds a study to the benchmark. Example:

benchmark.add_study(study1)
Parameters:

study (Study) – A Study object for which a benchmark should be run.

Return type:

None

With Client(asynchronous=True), await this method.

add_study_results

Benchmark.add_study_results(study)

Adds the results of a benchmark study at the end of an optimization run. Example:

benchmark.add_study_results(study1)
Parameters:

study (Study) – A Study object after the study was run.

Return type:

None

With Client(asynchronous=True), await this method.

close

Benchmark.close()

Finish using this benchmark through the client without stopping the server.

Call benchmark.close() with a synchronous client, or await benchmark.close() with Client(asynchronous=True).

Closing the client also closes its benchmarks, so you usually do not need to call this method separately.

With Client(asynchronous=True), await this method.

Return type:

None

get_data

Benchmark.get_data(x_type='num_evaluations', y_type='objective', average_type='mean', invert=False, log_scale=False, minimum=None, scales=None, norm=None, num_samples=100)

Get benchmark data. Example:

data = benchmark.get_data( x_type='num_evaluations', y_type='objective',
     average_type='mean')
plt.plot(data['X'][0],data['Y'][0])
Parameters:
  • x_type (Literal['num_evaluations', 'time']) – Data on x-axis. Can be either ‘num_evaluations’ or ‘time’. The time data is given in units of seconds.

  • y_type (Literal['objective', 'distance']) – Data type on y-axis. Can be either ‘objective’, ‘distance’, (i.e. accumulated minimum distance off all samples to overall minimum), or ‘min_distance’ (i.e. distance of current minimum to overall minimum).

  • average_type (Literal['mean', 'median']) – Type of averaging over study runs. Can be either ‘mean’ w.r.t. x-axis data or ‘median’ w.r.t. y-axis data

  • invert (bool) – If True, the objective is multiplied by -1. (Parameter not available for distance average types)

  • log_scale (bool) – If True, the output of Y and sdev are determined as mean and standard deviations of the natural logarithm of the considered y_type.

  • minimum (Optional[list[float]]) – Vector with minimum position. (Only available for distance average types)

  • scales (Optional[list[float]]) – Vector with positive weights for scaling distance in different directions. (Only available for distance average types)

  • norm (Union[str, int, None]) – Order of distance norm as defined in numpy.linalg.norm. (Only available for distance average types)

  • num_samples (int) – Number of samples on y-axis. (Only available for median average type or time on x-axis)

Return type:

dict[str, list[Union[str, float]]]

With Client(asynchronous=True), await this method.

run

Benchmark.run()

Run the benchmark after the evaluator has been set (see set_evaluator()). Example:

benchmark.run()

With Client(asynchronous=True), await this method.

Return type:

None

set_evaluator

Benchmark.set_evaluator(evaluator)[source]

Set the function that maps design parameters to an Observation. Example:

def evaluate(study: Study, x1: float, x2: float) -> Observation:
    observation = study.new_observation()
    observation.add(x1**2 + x2**2)
    return observation
benchmark.set_evaluator(evaluate)

Note

Call this function only after all studies have been added to the benchmark.

Parameters:

evaluator (Callable[..., Union[Observation, Awaitable[Observation]]]) – Function that evaluates the suggested parameters and returns an Observation with the result. The function must accept a "study" argument as well as an argument with the name of each design parameter and fixed environment parameter.

Return type:

None

studies

property Benchmark.studies: list[Study]

A list of studies to be run for the benchmark.

Client

class jcmoptimizer.Client(host=None, server_id=None, token=None, verbose=True, check=True, cloud_endpoint='https://optimizer.jcmwave.com/cloud/api/v1/', *, asynchronous=False, persistent=False)[source]

Connect to an optimization server and create studies and benchmarks.

If the Configuration is set up, no connection arguments are needed. For example:

design_space = [
    {'name': 'x1', 'type': 'continuous', 'domain': (-1.5, 1.5)},
    {'name': 'x2', 'type': 'continuous', 'domain': (-1.5, 1.5)},
]
with Client() as client:
    study = client.create_study(
        design_space=design_space, study_name='example'
    )

By default, each call waits for its result. When writing an async function, use Client(asynchronous=True) and await calls that contact the server. After defining your evaluation function, you can run a study:

async with Client(asynchronous=True) as client:
    study = await client.create_study(design_space=design_space)
    await study.configure(max_iter=20)
    study.set_evaluator(evaluate)
    await study.run()
    minimum = await study.driver.get_min_objective()

Methods that prepare observations or set the evaluation function, such as new_observation and set_evaluator, do not need await.

Use with Client() or async with Client(asynchronous=True) to close the connection automatically when you leave the block. If the client started a server, it also stops that server unless persistent=True. A server that was already running is left running.

Without a with block, call client.close() when finished, or await client.close() when using asynchronous=True.

Parameters:
  • host (Optional[str]) – Address of a running server, for example 'http://localhost:4554'. If neither host nor server_id is given, the client uses the configuration to find or start a server. For cloud connections, it first checks for a running server.

  • server_id (Optional[str]) – ID of a running cloud server to connect to when its address is not known.

  • token (Optional[str]) – API access token for cloud servers. Create a token on the JCMoptimizer Cloud website. If omitted, the token is read from the Configuration.

  • verbose (bool) – If true, print messages from the optimization server.

  • check (bool) – If true, check the server connection and version when connecting.

  • cloud_endpoint (str) – Address of the cloud API. Usually leave this unchanged.

  • asynchronous (bool) – If true, use await for calls that contact the server. Connection and server startup begin when entering async with or making the first awaited call. Default: false.

  • persistent (bool) – If true, a server started by this client keeps running after the client closes. Servers that were already running are always left running. Default: false.

check_server

Client.check_server()

Checks if the optimization server is running and if it is compatible to the client. Example:

>>> client.check_server()
Polling server at http://localhost:4554
Optimization server is running

With Client(asynchronous=True), await this method.

Return type:

None

close

Client.close()

Close the connection when you have finished using the client.

Any running operations started through this client are stopped. If the client started a server, it also stops that server unless persistent=True. A server that was already running is left running.

A with or async with block calls this method automatically. Otherwise, call client.close() or await client.close() when using asynchronous=True.

With Client(asynchronous=True), await this method.

Return type:

None

connect

Client.connect()

Connect to the configured server, starting one if needed.

Usually you do not need to call this method: the client connects automatically. You can call it to check the connection before creating a study.

With Client(asynchronous=True), await this method.

Return type:

None

create_benchmark

Client.create_benchmark(benchmark_id=None, num_average=6, remove_completed_studies=False)

Creates a new Benchmark object for benchmarking different optimization studies against each other. Example:

benchmark = client.create_benchmark(num_average=6)
Parameters:
  • benchmark_id (Optional[str]) – A unique identifier of the benchmark.

  • num_average (int) – Number of study runs to determine average study performance

  • remove_completed_studies (bool) – If true, studies that are completed (i.e. some stopping criterion was met) are removed from the server provided no other client is still using the study.

Return type:

Benchmark

With Client(asynchronous=True), await this method.

create_study

Client.create_study(design_space=None, environment=None, constraints=None, study_name=None, study_id=None, project_name='Project', project_id='project', save_dir=None, driver=None, output_precision=1e-10, dashboard=True, open_browser=None, clear_storage=False, extend_on_request=None, extend_on_suggestion=None, **kwargs)

Creates a new Study instance. Example:

study = client.create_study(
    design_space=design_space,
    study_name='example',
    study_id="example_01"
)
Parameters:
  • design_space (Optional[list[dict[str, Any]]]) –

    List of domain definitions for each parameter. A design space definition consists of a list of dictionary with the entries

    name:

    Name of the parameter. E.g. 'x1'. The name should contain no spaces and must not be equal to function names or mathematical constants like 'sin', 'cos', 'exp', 'pi' etc.

    type:

    Type of the parameter. Either 'continuous', 'discrete', or 'categorial'.

    domain:

    The domain of the parameter. For continuous parameters this is a tuple (min, max). For discrete parameters this is a list of values, e.g. [1.0,2.5,3.0]. For categorial inputs it is a list of strings, e.g. ['cat1','cat2','cat3']. Note, that categorial values are internally mapped to integer representations, which are allowed to have a correlation. The categorial values should therefore be ordered according to their similarity. For fixed parameters the domain is a single parameter value.

    Example:

    design_space = [
        {'name': 'x1', 'type': 'continuous', 'domain': (-2.0,2.0)},
        {'name': 'x2', 'type': 'continuous', 'domain': (-2.0,2.0)},
        {'name': 'x3', 'type': 'discrete', 'domain': [-1.0,0.0,1.0]},
        {'name': 'x4', 'type': 'categorial', 'domain': ['a','b']}
    ]
    

    If not specified, the design space configuration from the study history is used. If no historic information exists, an error is raised.

  • environment (Optional[list[dict[str, Any]]]) –

    Environment parameters are those which influence the behaviour of the system, but are not design parameters. Examples are uncontrollable environment parameters (e.g. temperature, time) or parameters that are scanned in each evaluation (e.g. wavelength, angle) for each run of the system can be described by environment parameters. Alternatively, scans can be described by surrogates that are trained on multiple inputs (one for each scan value). The environment definition consists of a list of dictionary with the entries:

    name:

    Name of the parameter. E.g. 'x1'. The name should contain no spaces and must not be equal to function names or mathematical constants like 'sin', 'cos', 'exp', 'PI' etc.

    type:

    Type of the parameter. Either 'variable' or 'fixed'. Numeric fixed parameters can be used in constraint functions or other expressions. String fixed parameters are labels passed to evaluators; they are excluded from numeric expressions. Use a new study ID when changing a fixed string value.

    domain:

    The domain of the parameter. For fixed parameters, this is a single numeric or string value; for variable parameters this can be a tuple (min, max). If no bounds are specified for variable parameters, the environment is considered to be unconstrained. In this case the scale has to be set.

    scale:

    The scale at which environment parameter changes affect the system. If the environment parameter describes unknown drifts and aging effects, the length scale is equal to the timescale at which the system behaviour changes due to drifts or aging.

    Example:

    environment = [
        {'name': 'wavelength', 'type': 'continuous', 'domain': (300, 600)},
        {'name': 'time', 'type': 'continuous', 'scale': 0.1},
        {'name': 'radius', 'type': 'fixed', 'domain': 1.5}
    ]
    

    If not specified, the environment configuration from the study history is used. If no historic information exists, the environment is assumed to be empty (environment = []).

  • constraints (Optional[list[dict[str, Any]]]) –

    List of constraints on the design space. Each list element is a dictionary with the entries

    name:

    Name of the constraint.

    constraint:

    A string defining an inequality constraint in the for a <= b or a >= b. The following operations and functions may be for example used: +,-,*,/,^,sqrt,sin,cos,tan,exp,log,log10,abs,round,sign,trunc. E.g. 'x1^2 + x2^2 <= sin(x1+x2)'. For a more complete list of supported functions, see the expression variable reference.

    Example:

    constraints = [
        {'name': 'circle', 'expression': 'x1^2 + x2^2 <= radius^2'},
        {'name': 'triangle', 'expression': 'x1 >= x2'},
    ]
    

    If not specified, the constraints configuration from the study history is used. If no historic information exists, the list of constraints is assumed to be empty (constraints = []).

  • study_name (Optional[str]) – The name of the study.

  • study_id (Optional[str]) – A unique identifier of the study. All relevant information on the study are saved in a file named study_id+’.jcmo’ If the study already exists, the design_space, environment, and constraints do not need to be provided. If not set, the study_id is set to a random unique string.

  • project_name (str) –

    The name of the project that the study belongs to.

    Note

    This parameter is only relevant when connecting to a cloud-based server.

  • project_id (str) –

    A unique identifier of the project.

    Note

    This parameter is only relevant when connecting to a cloud-based server.

  • save_dir (Optional[str]) –

    The path to a directory, where the study file (jcmo-file) is saved. Default is a directory in the system’s temporary directory.

    Note

    This parameter is only relevant when connecting to a self-hosted server.

  • driver (Optional[str]) – Driver used for the study. If not specified, the driver from the study history is used. If no historic information exists, the ‘ActiveLearning’ driver is used. For a list of drivers, see the driver reference.

  • output_precision (float) –

    Precision level for output of parameters.

    Note

    Rounding the output can potentially lead to a slight breaking of constraints.

  • dashboard (bool) – If true, a dashboard will be served for the study.

  • open_browser (Optional[bool]) – If true, the study dashboard will be opened in the default web browser. If not specified, the value is retrieved from the Configuration file.

  • clear_storage (bool) – If true, any stored data (study configuration, observations etc.) from previous runs of the study is cleared before creating the study.

  • extend_on_request (Optional[timedelta]) –

    If specified, the shutdown time of a cloud-based server is extended in each request, such that the server will always run for at least the specified amount of time after the request. If not specified, the value is retrieved from the Configuration file. Default: 5 minutes. Example:

    study = client.create_study(
       study_id="my-study",
       extend_on_request=timedelta(minutes=10)
    )
    

  • extend_on_suggestion (Optional[timedelta]) –

    If specified, the shutdown time of a cloud-based server is extended in each suggestion requested with study.get_suggestion(), such that the server will always run for at least the specified amount of time after the request. If not specified, the value is retrieved from the Configuration file. Default: 30 minutes. Example:

    study = client.create_study(
       study_id="my-study",
       extend_on_suggestion=timedelta(hours=1, minutes=30)
    )
    

Return type:

Study

With Client(asynchronous=True), await this method.

shutdown_server

Client.shutdown_server(force=False)

Shuts down the optimization server. Example:

client.shutdown_server()
Parameters:

force (bool) – If true, the optimization server is closed even if a study is not yet finished.

Return type:

None

With Client(asynchronous=True), await this method.

shutdown_server_at

Client.shutdown_server_at(shutdown_time)

Shuts down the optimization server at a certain time. Example:

import datetime as dt
client.shutdown_server_at(dt.datetime.now() + dt.timedelta(days=1))
Parameters:

shutdown_time (datetime) – The time at which the optimization server should be shut down.

Return type:

None

With Client(asynchronous=True), await this method.

Driver

class jcmoptimizer.Driver(study_id, project_id, requestor)[source]

This class provides methods for retrieving and setting driver-specific information of the study. Depending on the chosen driver of Client.create_study() the driver provides specific methods. More details for each driver are available in the driver reference. Example:

study.run()
driver = study.driver
min_objective_values = driver.historic_parameter_values(
    path="acquisition_function.min_objective")

The constructor should not be used directly since it does not create a driver on the server side. Instead, one should use Study.driver.

describe

Driver.describe()

Get description of all modules and their parameters that are used by the driver. Example:

description = driver.describe()
print(description["members"]["surrogates"]["0"])
Return type:

dict[str, Any]

Returns: A nested dictionary with description of submodules consisting

of a name and a descriptive text. If the entry describes a module, it has an additional "members" entry with dictionaries describing submodules and parameters.

With Client(asynchronous=True), await this method.

get_state

Driver.get_state(path=None)

Get state of the driver. Example:

best_sample = driver.get_state(path="best_sample")
Parameters:

path (Optional[str]) – A dot-separated path to a submodule or parameter. If none, the full state is returned.

Return type:

dict[str, Any]

Returns: If path is None, a dictionary with information of driver state.

Note

A description of the meaning of each entry in the state can be retrieved by describe().

With Client(asynchronous=True), await this method.

historic_parameter_values

Driver.historic_parameter_values(path)

Get the values of an internal parameter for each iteration of the study. Example:

min_objective_values = driver.historic_parameter_values(
    path="acquisition_function.min_objective")
Parameters:

path (str) – A dot-separated path to the parameter.

Return type:

list[Any]

Note

A description of the meaning of each parameter can be retrieved by describe().

With Client(asynchronous=True), await this method.

Observation

class jcmoptimizer.Observation[source]

This class provides a container to collect data to be sent to the optimizer. This includes scalar or vectorial inputs for the objective or surrogate models of an active learning-based driver.

add

Observation.add(value, derivative=None, uncertainty=None, model_name=None, environment_value=None)[source]

Add data to observation. Example:

obs.add(val)
obs.add(dval_dx1, derivative='x1')
obs.add(dval_dx2, derivative='x2')
Parameters:
  • value (Union[float, list[float]]) – Numerical value or list of values.

  • derivative (Optional[str]) – If the values are derivatives w.r.t. a design or environment parameter, this should be the name of the parameter.

  • uncertainty (Union[float, list[float], None]) – The uncertainty of the provided values, i.e. the estimated standard deviation of multiple observations for same parameter.

  • model_name (Optional[str]) – Name of the surrogate model that is trained on the data. Can be also None for drivers that do not support multiple models.

  • environment_value (Optional[list[float]]) – List of environment value for all entries of the environment of the study. Optionally, entries for different environment values can be added consecutively, such that also scans of environment values can be collected into one observation.

Return type:

None

Server

class jcmoptimizer.Server(server_location=None, persistent=False, server_id=None, server_name=None, shutdown_at=None, token=None, cloud_endpoint='https://optimizer.jcmwave.com/cloud/api/v1/', version=None, jcmoptimizer_dir=None, license_dir=None, port=None, timeout=40.0, max_retries=1, jcm_optimizer_path=None)[source]

This class allows to start a local or cloud-based optimization server. If the Configuration is fully set up, the server can be initialized without any arguments. Example:

server = Server()
client = Client(host=server.host)
study = client.create_study(...)

Note

If you know the ID of a running cloud-based server, you can directly connect to it via client = Client(server_id='leonardo'). Likewise, if you know the port of a local server you can connect via client = Client(host='http://localhost:4554').

General Arguments

The following arguments are available for all server instances.

type server_location:

Optional[Literal['cloud', 'local']]

param server_location:

Location of the JCMoptimizer server. If 'cloud', a server instance is started in the cloud. If 'local', a local JCMoptimizer installation is used. If not specified, the location is retrieved from the Configuration file.

type persistent:

bool

param persistent:

If true, the server continues to run even after the Python script has finished. To shutdown a server later on, one can reconnect to it:

client = Client(host="http://localhost:4554")
client.shutdown_server()

Cloud Server Arguments

The following arguments are available for a server instance running in the cloud (i.e. server_location='cloud').

type server_id:

Optional[str]

param server_id:

The ID of the new server. If a cloud server with the given ID exists, an error is raised. Example:

server = Server(server_location='cloud', server_id="my_server")
client = Client(server_id=server.id)
type server_name:

Optional[str]

param server_name:

Some descriptive name of the server. If not specified, the server name is chosen automatically.

type shutdown_at:

Optional[datetime]

param shutdown_at:

The time when the server should automatically shut down. If not specified, the shutdown time is chosen automatically. Example:

import datetime as dt
server = Server(
    server_location='cloud',
    shutdown_at=dt.datetime.now() + dt.timedelta(hours=3)
)
type token:

Optional[str]

param token:

API access token. This is required for cloud servers. In order to create a token, visit the JCMoptimizer Cloud website. If not specified, the token is retrieved from the Configuration file.

type cloud_endpoint:

str

param cloud_endpoint:

The URL of the cloud API endpoint. This argument should be usually left at its default value.

type version:

Optional[str]

param version:

The version of the cloud optimizer to use. This argument should be left at its default value, which matches the client version.

Local Server Arguments

The following arguments are available for a server instance running locally (i.e. server_location='local').

type jcmoptimizer_dir:

Optional[str]

param jcmoptimizer_dir:

The path of the JCMoptimizer installation. If not specified, the directory is retrieved from the Configuration file.

type license_dir:

Optional[str]

param license_dir:

Directory containing license information for JCMsuite, e.g. /path/to/JCMsuite/license. If not specified, the directory is retrieved from the Configuration file.

type port:

Optional[int]

param port:

The port that the optimization server is listening to. If not specified, the port is chosen automatically.

type timeout:

float

param timeout:

The maximum amount of time to wait for the server startup.

type max_retries:

int

param max_retries:

The maximum number of attempts to start the server after a timeout.

host

property Server.host: str

The host name of the server

id

property Server.id: str

The ID of the cloud server.

Raises:

AttributeError – If the server is not running in the cloud.

pid

property Server.pid: int

The process id of the server.

Raises:

AttributeError – If the server is not running locally.

port

property Server.port: int

The port that the server is listening on.

shutdown

Server.shutdown(force=False)

Stop this optimization server.

Parameters:

force (bool) – If true, stop the server even if a study has not finished. Default: false.

Return type:

None

Study

class jcmoptimizer.Study(study_id, project_id, driver, requestor, extend_on_request=None, extend_on_suggestion=None)[source]

Configure and run an optimization study and retrieve its results.

Create a study with Client.create_study(), then provide a function that evaluates each suggested set of parameters. For example:

def evaluate(study: Study, x1: float, x2: float) -> Observation:
    observation = study.new_observation()
    observation.add(x1**2 + x2**2)
    return observation

study.configure(max_iter=30, num_parallel=3)
study.set_evaluator(evaluate)
study.run()

run() requests suggestions, calls your function and submits its observations automatically. To evaluate suggestions one at a time yourself:

while not study.is_done():
    suggestion = study.get_suggestion()
    observation = evaluate(study, **suggestion.kwargs)
    study.add_observation(observation, suggestion.id)

With Client(asynchronous=True), use await for calls that contact the server, including configure() and run(). See Client for an example.

add_many

Study.add_many(observations, design_values=None, environment_values=None, acquisition_times=None, check=True, suggestion_ids=None)

Adds many observations to the study. Example:

study.add_many(observations, design_values)
Parameters:
  • observations (list[Observation]) – List of Observation objects for each sample (see new_observation())

  • design_values (Optional[list[list[Union[float, str]]]]) – List of design values. This is required unless suggestion_ids is provided. E.g. [[0.1, 1.0, 'cat1'], [0.2, 2.0, 'cat2']]

  • environment_values (Optional[list[list[float]]]) – Optional list of environment values. If not specified, the last known environment values are taken. E.g. [[1.0, 2.0], [1.1, 2.3]]

  • acquisition_times (Optional[list[float]]) – Optional list of times required to acquire each observation.

  • check (bool) – If true, the validity of the observation is checked

  • suggestion_ids (Optional[list[int]]) – Optional list of ids of the corresponding open suggestions. Their design and environment values are used and the suggestions are consumed when the batch is added successfully. If design_values is also provided, the suggestion values take precedence.

Return type:

None

Note

The surrogate is retrained once after the complete batch. Historic variable and objective values are stored per observation, while other driver-specific values represent the state after the complete batch.

With Client(asynchronous=True), await this method.

add_observation

Study.add_observation(observation, suggestion_id=None, design_value=None, environment_value=None, acquisition_time=None, check=True)

Adds an observation to the study. Example:

study.add_observation(observation, suggestion.id)
Parameters:
  • observation (Observation) – Observation object with added values (see new_observation())

  • suggestion_id (Optional[int]) – Id of the corresponding suggestion if it exists.

  • design_value (Optional[list[Union[float, str]]]) – If the observation does not belong to an open suggestion, the corresponding design value must be provided as a list of floats for continuous and discrete parameters or string for categorial parameters. E.g. [0.1, 2.0, 'cat1'].

  • environment_value (Optional[list[float]]) – If an environment parameters are specified, this specifies the value of variable environment parameters as a list of floats that is valid for all values added to the observation. E.g. [1.0, 2.0]. Alternatively, one can also set different environment values for each entry of the observation (see add()).

  • acquisition_time (Optional[float]) – If the observation does not belong to an open suggestion, it is possible to specify the time it took to retrieve the observation (e.g. the computation time). This information can be used to adapt the effort of computing the next suggestions.

  • check (bool) – If true, the validity of the observation is checked

Return type:

None

With Client(asynchronous=True), await this method.

add_observation_data

Study.add_observation_data(data)

Add data from another study to the study. Example:

obs_data = study.get_observation_data()
other_study.add_observation_data(obs_data)
Parameters:

data (dict[str, Any]) – Dict with observation data. See get_observation_data() for the details.

Return type:

None

With Client(asynchronous=True), await this method.

clear_all_suggestions

Study.clear_all_suggestions()

Clear all open suggestions. Example:

study.clear_all_suggestions()
Return type:

None

Note

The study only creates num_parallel suggestions (see configure()) until it waits for an observation to be added (see add_observation()) or a suggestion to be cleared.

With Client(asynchronous=True), await this method.

clear_suggestion

Study.clear_suggestion(suggestion_id, message='')

If the evaluation for a certain suggestion fails, the suggestion can be cleared from the study. Example:

study.clear_suggestion(suggestion.id, 'Computation failed')

Note

The study only creates num_parallel suggestions (see configure()) until it waits for an observation to be added (see add_observation()) or a suggestion to be cleared.

Parameters:
  • suggestion_id (int) – Id of the suggestion to be cleared.

  • message (str) – An optional message that is printed out.

Return type:

None

With Client(asynchronous=True), await this method.

close

Study.close()

Finish using this study through the client. Saved observations are kept.

Call study.close() with a synchronous client, or await study.close() with Client(asynchronous=True).

This does not stop the server. Closing the client also closes its studies, so you usually do not need to call this method separately.

With Client(asynchronous=True), await this method.

Return type:

None

configuration

property Study.configuration: dict[str, Any]

The current study configuration.

With Client(asynchronous=True), use await study.get_configuration() instead of this property.

configure

Study.configure(num_parallel=1, max_iter=None, max_time=None, **kwargs)

Configures the study for its run. Example:

study.configure(max_iter=100, num_parallel=5)
Parameters:
  • num_parallel (int) – Number of parallel observations of the evaluator function (default: 1).

  • max_iter (Optional[int]) – Maximum number of evaluations of the evaluator 2 function (default: inf).

  • max_time (Optional[float]) – Maximum optimization time in seconds (default: inf).

Return type:

None

Note

The full list of parameters depends on the chosen driver. For a parameter description, see the the corresponding driver in the driver reference.

With Client(asynchronous=True), await this method.

describe

Study.describe()

Get description of all modules and their parameters that are used by the study. Example:

description = study.describe()
print(description["observation"]["acquisition_time"])
print(description["driver"]["members"]["surrogates"]["0"])

Returns: A dictionary with the root entries: :rtype: dict[str, Any]

driver:

Nested dictionary with description of submodules consisting of a name and a descriptive text. If the entry describes a module, it has an additional "members" entry with dictionaries describing submodules and parameters.

observation:

Dictionary with a description of the parameters of an observation.

suggestion:

Dictionary with a description of the parameters of a suggestion of the driver.

With Client(asynchronous=True), await this method.

driver

property Study.driver: Driver

The driver of the study. For a documentation see the Driver Reference of the corresponding driver.

get_configuration

Study.get_configuration()

Return the current configuration for the driver.

Use it to configure another study. Example:

config = study.get_configuration()
study2.configure(**config)

With Client(asynchronous=True), await this method.

Return type:

dict[str, Any]

get_observation_data

Study.get_observation_data()

Get table with data of the observations. This can be used to copy the data manually to another study. Example:

obs_data = study.get_observation_data()
other_study.add_observation_data(obs_data)
Return type:

dict[str, Any]

Returns: Dictionary, where each entry holds an equally long list of observation

data. The keys of the dictionary are:

value:

Observed value of black-box function

derivative:

Name of derivative parameter or None for non-derivative observation

uncertainty:

Uncertainty of observed value or None if no uncertainty

model_name:

Name of the surrogate model that is trained on the data or None

design_value:

Value of design parameters

environment_value:

Value of environment parameters or None if no environment is specified

With Client(asynchronous=True), await this method.

get_state

Study.get_state(path=None)

Get state of the study. Example:

acquisition_time = study.get_state(
    path="observation.acquisition_time"
)
Parameters:

path (Optional[str]) – A dot-separated path to a submodule or parameter. If none, the full state is returned.

Return type:

dict[str, Any]

Returns: If path is None, a dictionary with the following entries

is returned:

driver:

Dictionary with information of driver state.

observation:

Dictionary with information of the latest observation.

suggestion:

Dictionary with information about the suggestion that corresponds to the last observation

Note

A description of the meaning of each entry in the state can be retrieved by describe().

With Client(asynchronous=True), await this method.

get_suggestion

Study.get_suggestion(environment_value=None)

Get a new suggestion to be evaluated by the user. Example:

def evaluate(study: Study, x1: float, x2: float) -> Observation:
   obs = study.new_observation()
   obs.add(x1**2 + x2**2)
   return obs

suggestion = study.get_suggestion()
obs = evaluate(study, **suggestion.kwargs)
study.add_observation(observation=obs, suggestion_id=suggestion.id)
Parameters:

environment_value (Optional[list[float]]) – If an environment is specified, this optional argument specifies the list of variable environment parameter values, for which a suggestion should be computed. E.g. [0.1, 1.2]. If an environment exists and no values are specified, the last known environment values are used.

Return type:

Suggestion

Warning

If num_parallel suggestions are already waiting for results, this call waits. Submit an observation or clear an unfinished suggestion before requesting another one. Use run() to manage parallel evaluations automatically.

With Client(asynchronous=True), await this method.

historic_parameter_values

Study.historic_parameter_values(path)

Get the values of an internal parameter for each iteration of the study. Example:

acquisition_times = study.historic_parameter_values(
    path="observation.acquisition_time")
Parameters:

path (str) – A dot-separated path to the parameter.

Return type:

list[Any]

Note

A description of the meaning of each parameter can be retrieved by describe().

With Client(asynchronous=True), await this method.

is_done

Study.is_done()

Checks if the study has finished. Example:

if study.is_done(): break
Return type:

bool

Returns: True if some stopping criterion set by

configure() was met.

Note

Before returning true, the function call waits until all open suggestions have been added to the study.

With Client(asynchronous=True), await this method.

new_observation

Study.new_observation()[source]

Create a new Observation object that allows to add data via add(). Example:

observation = study.new_observation()
observation.add(1.2)
observation.add(0.1, derivative='x1')
Return type:

Observation

run

Study.run()

Evaluate suggestions until a stopping condition from configure() is met.

First register your evaluation function with set_evaluator(). run() requests suggestions, evaluates them and submits the observations. num_parallel controls how many evaluations can run at the same time. The evaluation function can be defined with def or async def.

If an evaluation fails, the study continues with a new suggestion. After max_num_failed consecutive failures (default: 3), it stops and reports the last error. Errors when communicating with the server stop the run immediately.

Interrupting the run with Ctrl-C, or cancelling an awaited run, stops the study and clears its unfinished suggestions. Stopping may take time if a server request is still being processed. Observations already submitted are kept, so you can continue the study later.

With Client(asynchronous=True), await this method.

Return type:

None

set_evaluator

Study.set_evaluator(evaluator)[source]

Set the function that maps design parameters to an Observation. Example:

def evaluate(study: Study, x1: float, x2: float) -> Observation:
    observation = study.new_observation()
    observation.add(x1**2 + x2**2)
    return observation
study.set_evaluator(evaluate)
Parameters:

evaluator (Callable[..., Union[Observation, Awaitable[Observation]]]) – Function that evaluates the suggested parameters and returns an Observation with the result. The function must accept a "study" argument as well as an argument with the name of each design parameter and fixed environment parameter. You can define the function with def or async def. With num_parallel > 1, several evaluations may run at once; avoid changing shared data without protecting it from other calls.

Return type:

None

start_clock

Study.start_clock()

The optimization stops after the time max_time (see configure()). This function resets the clock to zero. Example:

study.start_clock()
Return type:

None

Note

The clock is also set to zero by calling configure().

With Client(asynchronous=True), await this method.

Suggestion

class jcmoptimizer.Suggestion(sample, id)[source]

This class provides the sample to be evaluated and the id which is required to identify results for this suggestion. Example:

def evaluate(study: Study, x1: float, x2: float) -> Observation:
   obs = study.new_observation()
   obs.add(x1**2 + x2**2)
   return obs

suggestion = study.get_suggestion()
obs = evaluate(study, **suggestion.kwargs)
study.add_observation(observation=obs, suggestion_id=suggestion.id)

The constructor should not be used directly. Instead, one creates suggestions using Study.get_suggestion().

id

property Suggestion.id: int

The id of the suggestion.

kwargs

property Suggestion.kwargs: dict[str, str | float]

Dictionary which maps names of design parameters to their values for which an observation is suggested.