Links

Parameter Constraints

Parameter Constraints can be added to an experiment definition to search for the optimum within a limited region of parameter space. Once parameter constraints are defined, all the configurations generated by SigOpt are guaranteed to satisfy them.

Linear Inequality Constraints

Linear inequality constraints can be used to define restrictions that depend on multiple parameters. Multiple linear constraints can be defined at the same time where each constraint must affect more than one parameter. The region where all the constraints are satisfied is called the feasible region. SigOpt will find the optimum inside the feasible region, while guaranteeing that no points are placed outside the feasible region. In the case of multiple constraints, SigOpt also checks the existence of the feasible region at experiment creation. For constraints that cannot be explicitly expressed as linear inequalities (e.g., nonlinear or blackbox), refer to the Metric Constraints documentation on defining constraints through thresholding on metric values.

Defining an Experiment with Linear Inequality Constraints

A SigOpt Experiment with linear inequality constraints is defined by the expression:
w1x1+w2x2++wkxkthresholdw_1 x_1 + w_2 x_2 + \dots + w_k x_k \geq \text{threshold}
The weight
ww
of each parameter as well as the threshold inequality value can be set at experiment creation.
If the constraints are defined such that a feasible region does not exist, or where a constraint affects only one parameter (i.e. the constraint is encoded in the bounds of the respective parameter), SigOpt will return an API Error.

Core Module

Python
Bash
Java
from sigopt import Connection
conn = Connection(client_token="USER_TOKEN")
experiment = conn.experiments().create(
name='Experiment with constraints',
parameters=[
dict(name='alpha', type='double', bounds=dict(min=0.0, max=1.0)),
dict(name='beta', type='double', bounds=dict(min=0.0, max=1.0)),
dict(name='gamma', type='int', bounds=dict(min=0, max=10)),
dict(name='theta', type='int', bounds=dict(min=0, max=10)),
],
metrics=[dict(name='metric_value', objective='maximize')],
observation_budget=80,
parallel_bandwidth=1,
linear_constraints=[
# Constraint inequality: alpha + beta <= 1
dict(
type='less_than',
threshold=1,
terms=[
dict(name='alpha', weight=1),
dict(name='beta', weight=1),
],
),
# Constraint inequality: 3 * gamma - 5 * theta >= 0
dict(
type='greater_than',
threshold=0,
terms=[
dict(name='gamma', weight=3),
dict(name='theta', weight=-5),
],
),
],
)
EXPERIMENT=curl -s -X POST https://api.sigopt.com/v1/experiments -u "$SIGOPT_API_TOKEN": \
-H "Content-Type: application/json" -d "`cat experiment_meta.json`"
JSON file defining the Experiment:
experiment_meta.json
{
"name": "Experiment with constraints",
"parameters": [
{
"name": "alpha",
"type": "double",
"bounds": {
"min": 0.0,
"max": 1.0
}
},
{
"name": "beta",
"type": "double",
"bounds": {
"min": 0.0,
"max": 1.0
}
},
{
"name": "gamma",
"type": "int",
"bounds": {
"min": 0,
"max": 10
}
},
{
"name": "theta",
"type": "int",
"bounds": {
"min": 0,
"max": 10
}
}
],
"metrics": [
{
"name": "metric_value",
"objective": "maximize"
}
],
"observation_budget": 80,
"parallel_bandwidth": 1,
"linear_constraints": [
{
"type": "less_than",
"threshold": 1,
"terms": [
{
"name": "alpha",
"weight": 1
},
{
"name": "beta",
"weight": 1
}
]
},
{
"type": "greater_than",
"threshold": 0,
"terms": [
{
"name": "gamma",
"weight": 3
},
{
"name": "theta",
"weight": -5
}
]
}
]
}
import com.sigopt.SigOpt;
import com.sigopt.exception.SigoptException;
import com.sigopt.model.*;
import java.util.Arrays;
public class YourSigoptExperiment {
public static Experiment createExperiment() throws SigoptException {
Experiment experiment = Experiment.create()
.data(
new Experiment.Builder()
.name("Experiment with constraints")
.parameters(java.util.Arrays.asList(
new Parameter.Builder()
.name("alpha")
.bounds(new Bounds.Builder()
.min(0)
.max(1)
.build())
.type("double")
.build(),
new Parameter.Builder()
.name("beta")
.bounds(new Bounds.Builder()
.min(0)
.max(1)
.build())
.type("double")
.build(),
new Parameter.Builder()
.name("gamma")
.bounds(new Bounds.Builder()
.min(0)
.max(10)
.build())
.type("int")
.build(),
new Parameter.Builder()
.name("theta")
.bounds(new Bounds.Builder()
.min(0)
.max(10)
.build())
.type("int")
.build()
))
.linearConstraints(java.util.Arrays.asList(
new LinearConstraint.Builder()
.terms(java.util.Arrays.asList(
new ConstraintTerm.Builder()
.name("alpha")
.weight(1)
.build(),
new ConstraintTerm.Builder()
.name("beta")
.weight(1)
.build()
))
.threshold(1)
.type("less_than")
.build(),
new LinearConstraint.Builder()
.terms(java.util.Arrays.asList(
new ConstraintTerm.Builder()
.name("gamma")
.weight(3)
.build(),
new ConstraintTerm.Builder()
.name("theta")
.weight(-5)
.build()
))
.threshold(0)
.type("greater_than")
.build()
))
.metrics(java.util.Arrays.asList(
new Metric.Builder()
.name("metric_value")
.objective("maximize")
.strategy("optimize")
.build()
))
.observationBudget(80)
.parallelBandwidth(1)
.type("offline")
.build()
)
.call();
return experiment;
}

AI Module

Python
YAML
sigopt.create_experiment(
name="Single metric optimization with linear constraints",
type="offline",
project="sigopt-examples",
parameters=[
dict(name='alpha', type='double', bounds=dict(min=0.0, max=1.0)),
dict(name='beta', type='double', bounds=dict(min=0.0, max=1.0)),
dict(name='gamma', type='int', bounds=dict(min=0, max=10)),
dict(name='theta', type='int', bounds=dict(min=0, max=10)),
],
metrics=[dict(name='metric_value', objective='maximize')],
budget=80,
parallel_bandwidth=1,
linear_constraints=[
# Constraint inequality: alpha + beta <= 1
dict(
type='less_than',
threshold=1,
terms=[
dict(name='alpha', weight=1),
dict(name='beta', weight=1),
],
),
# Constraint inequality: 3 * gamma - 5 * theta >= 0
dict(
type='greater_than',
threshold=0,
terms=[
dict(name='gamma', weight=3),
dict(name='theta', weight=-5),
],
),
],
)
name: Single metric optimization with linear constraints
type: offline
project: sigopt-examples
parameters:
- name: alpha
type: double
bounds:
min: 0.0
max: 1.0
- name: beta
type: double
bounds:
min: 0.0
max: 1.0
- name: gamma
type: int
bounds:
min: 0
max: 10
- name: theta
type: int
bounds:
min: 0
max: 10
metrics:
- name: metric_value
objective: maximize
budget: 80
parallel_bandwidth: 1
linear_constraints:
- type: less_than
threshold: 1
terms:
- name: alpha
weight: 1
- name: beta
weight: 1
- type: greater_than
threshold: 0
terms:
- name: gamma
weight: 3
- name: theta
weight: -5
Nonzero weights are included only for the parameters involved in each constraint, e.g., observe that alpha is not involved in the second constraint.
While the constraint types are less_than or greater_than, these are not strict inequalities, and we allow for equality as well. This will likely be more relevant to users defining constraints on int parameters.

Limitations

  • The experiment type must be offline or random
  • The constraints can be defined in terms of any set of parameters of type double or int
  • Mixed variable constraints are not allowed, i.e., a constraint involving both double and int parameters
  • Integer constraints can be defined on at most 10 unique int parameters
  • For Experiments with conditional parameters, constraints can only be defined for unconditional parameters
  • The constraint definitions and constraint parameters cannot be updated during the experiment