VOCS data structure¶
Variables, Objectives, Constraints, and other Settings (VOCS) helps define our optimization problems.
In [1]:
Copied!
from xopt.vocs import VOCS
from xopt.vocs import (
get_objective_data,
random_inputs,
get_constraint_data,
get_feasibility_data,
normalize_inputs,
denormalize_inputs,
)
from gest_api.vocs import MaximizeObjective
import pandas as pd
import numpy as np
import yaml
from xopt.vocs import VOCS
from xopt.vocs import (
get_objective_data,
random_inputs,
get_constraint_data,
get_feasibility_data,
normalize_inputs,
denormalize_inputs,
)
from gest_api.vocs import MaximizeObjective
import pandas as pd
import numpy as np
import yaml
In [2]:
Copied!
Y = """
variables:
a: [0, 1e3] # Note that 1e3 usually parses as a str with YAML.
b: [-1, 1]
objectives:
c: maximize
d: minimize
constraints:
e: ['Less_than', 2]
f: ['greater_than', 0]
constants:
g: 123
"""
vocs = VOCS(**yaml.safe_load(Y))
vocs
Y = """
variables:
a: [0, 1e3] # Note that 1e3 usually parses as a str with YAML.
b: [-1, 1]
objectives:
c: maximize
d: minimize
constraints:
e: ['Less_than', 2]
f: ['greater_than', 0]
constants:
g: 123
"""
vocs = VOCS(**yaml.safe_load(Y))
vocs
Out[2]:
VOCS(variables={'a': ContinuousVariable(dtype=None, default_value=None, domain=[0.0, 1000.0]), 'b': ContinuousVariable(dtype=None, default_value=None, domain=[-1.0, 1.0])}, objectives={'c': MaximizeObjective(dtype=None), 'd': MinimizeObjective(dtype=None)}, constraints={'e': LessThanConstraint(dtype=None, value=2.0), 'f': GreaterThanConstraint(dtype=None, value=0.0)}, constants={'g': Constant(dtype=None, value=123)}, observables={})
In [3]:
Copied!
# as dict
dict(vocs)
# as dict
dict(vocs)
Out[3]:
{'variables': {'a': ContinuousVariable(dtype=None, default_value=None, domain=[0.0, 1000.0]),
'b': ContinuousVariable(dtype=None, default_value=None, domain=[-1.0, 1.0])},
'objectives': {'c': MaximizeObjective(dtype=None),
'd': MinimizeObjective(dtype=None)},
'constraints': {'e': LessThanConstraint(dtype=None, value=2.0),
'f': GreaterThanConstraint(dtype=None, value=0.0)},
'constants': {'g': Constant(dtype=None, value=123)},
'observables': {}}
In [4]:
Copied!
# re-parse dict
vocs2 = VOCS(**dict(vocs))
# re-parse dict
vocs2 = VOCS(**dict(vocs))
In [5]:
Copied!
# Check that these are the same
vocs2 == vocs
# Check that these are the same
vocs2 == vocs
Out[5]:
True
In [6]:
Copied!
# This replaces the old vocs["variables"]
getattr(vocs, "variables")
# This replaces the old vocs["variables"]
getattr(vocs, "variables")
Out[6]:
{'a': ContinuousVariable(dtype=None, default_value=None, domain=[0.0, 1000.0]),
'b': ContinuousVariable(dtype=None, default_value=None, domain=[-1.0, 1.0])}
In [7]:
Copied!
vocs.objectives["c"]
vocs.objectives["c"]
Out[7]:
MaximizeObjective(dtype=None)
In [8]:
Copied!
isinstance(vocs.objectives["c"], MaximizeObjective)
isinstance(vocs.objectives["c"], MaximizeObjective)
Out[8]:
True
In [9]:
Copied!
# json
vocs.model_dump_json()
# json
vocs.model_dump_json()
Out[9]:
'{"variables":{"a":{"dtype":null,"default_value":null,"domain":[0.0,1000.0],"type":"ContinuousVariable"},"b":{"dtype":null,"default_value":null,"domain":[-1.0,1.0],"type":"ContinuousVariable"}},"objectives":{"c":{"dtype":null,"type":"MaximizeObjective"},"d":{"dtype":null,"type":"MinimizeObjective"}},"constraints":{"e":{"dtype":null,"value":2.0,"type":"LessThanConstraint"},"f":{"dtype":null,"value":0.0,"type":"GreaterThanConstraint"}},"constants":{"g":{"dtype":null,"value":123,"type":"Constant"}},"observables":{}}'
Objective Evaluation¶
In [10]:
Copied!
data = pd.DataFrame(random_inputs(vocs, 10))
# Add some outputs
data["c"] = data["a"] + data["b"]
data["d"] = data["a"] - data["b"]
data["e"] = data["a"] * 2 + data["b"] * 2
data["f"] = data["a"] * 2 - data["b"] * 2
data.index = np.arange(len(data)) + 5 # custom index
data
data = pd.DataFrame(random_inputs(vocs, 10))
# Add some outputs
data["c"] = data["a"] + data["b"]
data["d"] = data["a"] - data["b"]
data["e"] = data["a"] * 2 + data["b"] * 2
data["f"] = data["a"] * 2 - data["b"] * 2
data.index = np.arange(len(data)) + 5 # custom index
data
Out[10]:
| a | b | g | c | d | e | f | |
|---|---|---|---|---|---|---|---|
| 5 | 878.785524 | 0.657096 | 123 | 879.442619 | 878.128428 | 1758.885239 | 1756.256855 |
| 6 | 505.085243 | -0.740684 | 123 | 504.344558 | 505.825927 | 1008.689117 | 1011.651854 |
| 7 | 933.343241 | 0.622494 | 123 | 933.965734 | 932.720747 | 1867.931469 | 1865.441494 |
| 8 | 763.850721 | -0.528342 | 123 | 763.322379 | 764.379064 | 1526.644758 | 1528.758128 |
| 9 | 942.075416 | 0.286217 | 123 | 942.361633 | 941.789200 | 1884.723266 | 1883.578399 |
| 10 | 348.472777 | 0.409085 | 123 | 348.881863 | 348.063692 | 697.763725 | 696.127385 |
| 11 | 864.811765 | 0.148920 | 123 | 864.960685 | 864.662845 | 1729.921370 | 1729.325691 |
| 12 | 604.852508 | 0.908629 | 123 | 605.761137 | 603.943879 | 1211.522274 | 1207.887758 |
| 13 | 594.354394 | -0.767815 | 123 | 593.586579 | 595.122209 | 1187.173157 | 1190.244418 |
| 14 | 813.408393 | -0.464690 | 123 | 812.943703 | 813.873083 | 1625.887407 | 1627.746167 |
In [11]:
Copied!
# These are in standard form for minimization, available as a function
get_objective_data(vocs, data)
# These are in standard form for minimization, available as a function
get_objective_data(vocs, data)
Out[11]:
| objective_c | objective_d | |
|---|---|---|
| 5 | -879.442619 | 878.128428 |
| 6 | -504.344558 | 505.825927 |
| 7 | -933.965734 | 932.720747 |
| 8 | -763.322379 | 764.379064 |
| 9 | -942.361633 | 941.789200 |
| 10 | -348.881863 | 348.063692 |
| 11 | -864.960685 | 864.662845 |
| 12 | -605.761137 | 603.943879 |
| 13 | -593.586579 | 595.122209 |
| 14 | -812.943703 | 813.873083 |
In [12]:
Copied!
# use the to_numpy() method to convert for low level use.
get_objective_data(vocs, data).to_numpy()
# use the to_numpy() method to convert for low level use.
get_objective_data(vocs, data).to_numpy()
Out[12]:
array([[-879.44261948, 878.12842753],
[-504.34455835, 505.82592684],
[-933.96573444, 932.72074707],
[-763.32237913, 764.3790638 ],
[-942.36163306, 941.78919958],
[-348.88186255, 348.06369243],
[-864.96068482, 864.66284548],
[-605.76113688, 603.94387896],
[-593.58657852, 595.12220924],
[-812.94370327, 813.87308342]])
In [13]:
Copied!
get_constraint_data(vocs, data)
get_constraint_data(vocs, data)
Out[13]:
| constraint_e | constraint_f | |
|---|---|---|
| 5 | 1756.885239 | -1756.256855 |
| 6 | 1006.689117 | -1011.651854 |
| 7 | 1865.931469 | -1865.441494 |
| 8 | 1524.644758 | -1528.758128 |
| 9 | 1882.723266 | -1883.578399 |
| 10 | 695.763725 | -696.127385 |
| 11 | 1727.921370 | -1729.325691 |
| 12 | 1209.522274 | -1207.887758 |
| 13 | 1185.173157 | -1190.244418 |
| 14 | 1623.887407 | -1627.746167 |
In [14]:
Copied!
get_feasibility_data(vocs, data)
get_feasibility_data(vocs, data)
Out[14]:
| feasible_e | feasible_f | feasible | |
|---|---|---|---|
| 5 | False | True | False |
| 6 | False | True | False |
| 7 | False | True | False |
| 8 | False | True | False |
| 9 | False | True | False |
| 10 | False | True | False |
| 11 | False | True | False |
| 12 | False | True | False |
| 13 | False | True | False |
| 14 | False | True | False |
In [15]:
Copied!
# normalize inputs to unit domain [0,1]
normed_data = normalize_inputs(vocs, data)
normed_data
# normalize inputs to unit domain [0,1]
normed_data = normalize_inputs(vocs, data)
normed_data
Out[15]:
| a | b | |
|---|---|---|
| 5 | 0.878786 | 0.828548 |
| 6 | 0.505085 | 0.129658 |
| 7 | 0.933343 | 0.811247 |
| 8 | 0.763851 | 0.235829 |
| 9 | 0.942075 | 0.643108 |
| 10 | 0.348473 | 0.704543 |
| 11 | 0.864812 | 0.574460 |
| 12 | 0.604853 | 0.954314 |
| 13 | 0.594354 | 0.116092 |
| 14 | 0.813408 | 0.267655 |
In [16]:
Copied!
# and denormalize
denormalize_inputs(vocs, normed_data)
# and denormalize
denormalize_inputs(vocs, normed_data)
Out[16]:
| a | b | |
|---|---|---|
| 5 | 878.785524 | 0.657096 |
| 6 | 505.085243 | -0.740684 |
| 7 | 933.343241 | 0.622494 |
| 8 | 763.850721 | -0.528342 |
| 9 | 942.075416 | 0.286217 |
| 10 | 348.472777 | 0.409085 |
| 11 | 864.811765 | 0.148920 |
| 12 | 604.852508 | 0.908629 |
| 13 | 594.354394 | -0.767815 |
| 14 | 813.408393 | -0.464690 |
Error handling¶
In [17]:
Copied!
Y = """
variables:
a: [0, 1e3] # Note that 1e3 usually parses as a str with YAML.
b: [-1, 1]
objectives:
c: maximize
d: minimize
constraints:
e: ['Less_than', 2]
f: ['greater_than', 0]
constants:
g: 1234
"""
vocs = VOCS(**yaml.safe_load(Y))
Y = """
variables:
a: [0, 1e3] # Note that 1e3 usually parses as a str with YAML.
b: [-1, 1]
objectives:
c: maximize
d: minimize
constraints:
e: ['Less_than', 2]
f: ['greater_than', 0]
constants:
g: 1234
"""
vocs = VOCS(**yaml.safe_load(Y))
In [18]:
Copied!
d = {"a": [1, 2, 3]}
df = pd.DataFrame(d)
df2 = pd.DataFrame(df).copy()
df2["b"] = np.nan
df2["b"] - 1
d = {"a": [1, 2, 3]}
df = pd.DataFrame(d)
df2 = pd.DataFrame(df).copy()
df2["b"] = np.nan
df2["b"] - 1
Out[18]:
0 NaN 1 NaN 2 NaN Name: b, dtype: float64
In [19]:
Copied!
data["a"] = np.nan
data["a"] = np.nan
In [20]:
Copied!
a = 2
def f(x=a):
return x
a = 99
f()
a = 2
def f(x=a):
return x
a = 99
f()
Out[20]:
2
In [21]:
Copied!
pd.DataFrame(6e66, index=[1, 2, 3], columns=["A"])
pd.DataFrame(6e66, index=[1, 2, 3], columns=["A"])
Out[21]:
| A | |
|---|---|
| 1 | 6.000000e+66 |
| 2 | 6.000000e+66 |
| 3 | 6.000000e+66 |
In [22]:
Copied!
# These are in standard form for minimization
data = pd.DataFrame({"c": [1, 2, 3, 4]}, index=[9, 3, 4, 5])
get_objective_data(vocs, data)
# These are in standard form for minimization
data = pd.DataFrame({"c": [1, 2, 3, 4]}, index=[9, 3, 4, 5])
get_objective_data(vocs, data)
Out[22]:
| objective_c | objective_d | |
|---|---|---|
| 9 | -1.0 | inf |
| 3 | -2.0 | inf |
| 4 | -3.0 | inf |
| 5 | -4.0 | inf |