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 form_objective_data
import pandas as pd
import numpy as np
from xopt.vocs import VOCS
from xopt.vocs import form_objective_data
import pandas as pd
import numpy as np
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: 1234
"""
vocs = VOCS.from_yaml(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: 1234
"""
vocs = VOCS.from_yaml(Y)
vocs
Out[2]:
VOCS(variables={'a': [0.0, 1000.0], 'b': [-1.0, 1.0]}, constraints={'e': ['LESS_THAN', 2.0], 'f': ['GREATER_THAN', 0.0]}, objectives={'c': 'MAXIMIZE', 'd': 'MINIMIZE'}, constants={'g': 1234}, observables=[])
In [3]:
Copied!
# as dict
dict(vocs)
# as dict
dict(vocs)
Out[3]:
{'variables': {'a': [0.0, 1000.0], 'b': [-1.0, 1.0]},
'constraints': {'e': ['LESS_THAN', 2.0], 'f': ['GREATER_THAN', 0.0]},
'objectives': {'c': 'MAXIMIZE', 'd': 'MINIMIZE'},
'constants': {'g': 1234},
'observables': []}
In [4]:
Copied!
# re-parse dict
vocs2 = VOCS.from_dict(dict(vocs))
# re-parse dict
vocs2 = VOCS.from_dict(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': [0.0, 1000.0], 'b': [-1.0, 1.0]}
In [7]:
Copied!
vocs.objectives["c"] == "MAXIMIZE"
vocs.objectives["c"] == "MAXIMIZE"
Out[7]:
True
In [8]:
Copied!
# json
vocs.to_json()
# json
vocs.to_json()
Out[8]:
'{"variables":{"a":[0.0,1000.0],"b":[-1.0,1.0]},"constraints":{"e":["LESS_THAN",2.0],"f":["GREATER_THAN",0.0]},"objectives":{"c":"MAXIMIZE","d":"MINIMIZE"},"constants":{"g":1234},"observables":[]}'
Objective Evaluation¶
In [9]:
Copied!
data = pd.DataFrame(vocs.random_inputs(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(vocs.random_inputs(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[9]:
| a | b | g | c | d | e | f | |
|---|---|---|---|---|---|---|---|
| 5 | 429.279251 | -0.653713 | 1234 | 428.625538 | 429.932964 | 857.251076 | 859.865928 |
| 6 | 902.089175 | -0.534293 | 1234 | 901.554882 | 902.623468 | 1803.109765 | 1805.246937 |
| 7 | 861.252901 | -0.802566 | 1234 | 860.450334 | 862.055467 | 1720.900669 | 1724.110935 |
| 8 | 146.984367 | 0.008667 | 1234 | 146.993034 | 146.975700 | 293.986068 | 293.951400 |
| 9 | 932.937804 | 0.450766 | 1234 | 933.388570 | 932.487037 | 1866.777140 | 1864.974074 |
| 10 | 591.789090 | 0.333188 | 1234 | 592.122278 | 591.455902 | 1184.244556 | 1182.911805 |
| 11 | 923.904891 | 0.300432 | 1234 | 924.205323 | 923.604460 | 1848.410646 | 1847.208919 |
| 12 | 109.985820 | -0.546218 | 1234 | 109.439602 | 110.532038 | 218.879203 | 221.064075 |
| 13 | 11.928810 | 0.549522 | 1234 | 12.478332 | 11.379288 | 24.956665 | 22.758576 |
| 14 | 43.263545 | -0.511541 | 1234 | 42.752004 | 43.775086 | 85.504008 | 87.550172 |
In [10]:
Copied!
vocs.objectives
vocs.objectives
Out[10]:
{'c': 'MAXIMIZE', 'd': 'MINIMIZE'}
In [11]:
Copied!
# These are in standard form for minimization
form_objective_data(vocs.objectives, data)
# These are in standard form for minimization
form_objective_data(vocs.objectives, data)
Out[11]:
| objective_c | objective_d | |
|---|---|---|
| 5 | -428.625538 | 429.932964 |
| 6 | -901.554882 | 902.623468 |
| 7 | -860.450334 | 862.055467 |
| 8 | -146.993034 | 146.975700 |
| 9 | -933.388570 | 932.487037 |
| 10 | -592.122278 | 591.455902 |
| 11 | -924.205323 | 923.604460 |
| 12 | -109.439602 | 110.532038 |
| 13 | -12.478332 | 11.379288 |
| 14 | -42.752004 | 43.775086 |
In [12]:
Copied!
# This is also available as a method
vocs.objective_data(data)
# This is also available as a method
vocs.objective_data(data)
Out[12]:
| objective_c | objective_d | |
|---|---|---|
| 5 | -428.625538 | 429.932964 |
| 6 | -901.554882 | 902.623468 |
| 7 | -860.450334 | 862.055467 |
| 8 | -146.993034 | 146.975700 |
| 9 | -933.388570 | 932.487037 |
| 10 | -592.122278 | 591.455902 |
| 11 | -924.205323 | 923.604460 |
| 12 | -109.439602 | 110.532038 |
| 13 | -12.478332 | 11.379288 |
| 14 | -42.752004 | 43.775086 |
In [13]:
Copied!
# use the to_numpy() method to convert for low level use.
vocs.objective_data(data).to_numpy()
# use the to_numpy() method to convert for low level use.
vocs.objective_data(data).to_numpy()
Out[13]:
array([[-428.625538 , 429.932964 ],
[-901.55488237, 902.62346842],
[-860.45033436, 862.0554673 ],
[-146.99303387, 146.97569992],
[-933.38857003, 932.48703714],
[-592.12227789, 591.4559025 ],
[-924.20532317, 923.60445957],
[-109.43960163, 110.53203774],
[ -12.47833241, 11.37928801],
[ -42.75200409, 43.77508585]])
In [14]:
Copied!
vocs.constraint_data(data)
vocs.constraint_data(data)
Out[14]:
| constraint_e | constraint_f | |
|---|---|---|
| 5 | 855.251076 | -859.865928 |
| 6 | 1801.109765 | -1805.246937 |
| 7 | 1718.900669 | -1724.110935 |
| 8 | 291.986068 | -293.951400 |
| 9 | 1864.777140 | -1864.974074 |
| 10 | 1182.244556 | -1182.911805 |
| 11 | 1846.410646 | -1847.208919 |
| 12 | 216.879203 | -221.064075 |
| 13 | 22.956665 | -22.758576 |
| 14 | 83.504008 | -87.550172 |
In [15]:
Copied!
vocs.feasibility_data(data)
vocs.feasibility_data(data)
Out[15]:
| 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 [16]:
Copied!
# normalize inputs to unit domain [0,1]
normed_data = vocs.normalize_inputs(data)
normed_data
# normalize inputs to unit domain [0,1]
normed_data = vocs.normalize_inputs(data)
normed_data
Out[16]:
| a | b | |
|---|---|---|
| 5 | 0.429279 | 0.173144 |
| 6 | 0.902089 | 0.232853 |
| 7 | 0.861253 | 0.098717 |
| 8 | 0.146984 | 0.504333 |
| 9 | 0.932938 | 0.725383 |
| 10 | 0.591789 | 0.666594 |
| 11 | 0.923905 | 0.650216 |
| 12 | 0.109986 | 0.226891 |
| 13 | 0.011929 | 0.774761 |
| 14 | 0.043264 | 0.244230 |
In [17]:
Copied!
# and denormalize
vocs.denormalize_inputs(normed_data)
# and denormalize
vocs.denormalize_inputs(normed_data)
Out[17]:
| a | b | |
|---|---|---|
| 5 | 429.279251 | -0.653713 |
| 6 | 902.089175 | -0.534293 |
| 7 | 861.252901 | -0.802566 |
| 8 | 146.984367 | 0.008667 |
| 9 | 932.937804 | 0.450766 |
| 10 | 591.789090 | 0.333188 |
| 11 | 923.904891 | 0.300432 |
| 12 | 109.985820 | -0.546218 |
| 13 | 11.928810 | 0.549522 |
| 14 | 43.263545 | -0.511541 |
Error handling¶
In [18]:
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.from_yaml(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.from_yaml(Y)
In [19]:
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[19]:
0 NaN 1 NaN 2 NaN Name: b, dtype: float64
In [20]:
Copied!
data["a"] = np.nan
data["a"] = np.nan
In [21]:
Copied!
a = 2
def f(x=a):
return x
a = 99
f()
a = 2
def f(x=a):
return x
a = 99
f()
Out[21]:
2
In [22]:
Copied!
pd.DataFrame(6e66, index=[1, 2, 3], columns=["A"])
pd.DataFrame(6e66, index=[1, 2, 3], columns=["A"])
Out[22]:
| A | |
|---|---|
| 1 | 6.000000e+66 |
| 2 | 6.000000e+66 |
| 3 | 6.000000e+66 |
In [23]:
Copied!
# These are in standard form for minimization
data = pd.DataFrame({"c": [1, 2, 3, 4]}, index=[9, 3, 4, 5])
form_objective_data(vocs.objectives, data)
# These are in standard form for minimization
data = pd.DataFrame({"c": [1, 2, 3, 4]}, index=[9, 3, 4, 5])
form_objective_data(vocs.objectives, data)
Out[23]:
| objective_c | objective_d | |
|---|---|---|
| 9 | -1.0 | inf |
| 3 | -2.0 | inf |
| 4 | -3.0 | inf |
| 5 | -4.0 | inf |