Skip to content

Commit 94bada6

Browse files
ronald-jaepelschmoelder
authored andcommitted
Add variable dependencies to examples and docs.
1 parent a9a34a0 commit 94bada6

File tree

3 files changed

+144
-3
lines changed

3 files changed

+144
-3
lines changed

docs/source/user_guide/optimization/variable_dependencies.md

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ With linear combinations, variables are combined using weights or coefficients,
2828
For example, consider a process where the same parameter is used in multiple unit operations.
2929
To reduce the number of variables that the optimizer needs to consider, it is possible to add a single variable, which is then set on both evaluation objects in pre-processing.
3030
In other cases, the ratio between model parameters may be essential for the optimization problem.
31-
For instance, consider the equilibrium constant $k_{eq} = k_a / k_d$ for an adsorption process with adsorption rate $k_a$ and desorption rate $k_d$.
32-
Instead of exposing both $k_a$ and $k_d$ to the optimizer, it is usually beneficial to expose $k_a$ and $k_{eq}$.
33-
This way, the values for the equilibrium and the kinetics of the reaction can be found independently.
3431

3532

3633
```{figure} ./figures/transform_dependency.svg
@@ -61,3 +58,65 @@ optimization_problem.add_variable_dependency('var_2', ['var_0', 'var_1'], transf
6158
```
6259

6360
Note that generally bounds and linear constraints can still be specified independently for all variables.
61+
62+
## Adsorption rates example
63+
64+
For instance, consider an adsorption proces with an adsorption rate $k_a$ and a desorption rate $k_d$.
65+
Both influence the strength of the interaction as well as the dynamics of the interaction.
66+
By using the transformation $k_{eq} = k_a / k_d$ to calculate the equilibrium constant and $k_{kin} = 1 / k_d$ to calculate the kinetics constant, the values for the equilibrium and the kinetics of the reaction can be identified independently.
67+
First, the dependent variables $k_a$ and $k_d$ must be added as they are implemented in the underlying model.
68+
69+
```{code-cell} ipython3
70+
optimization_problem.add_variable(
71+
name='adsorption_rate',
72+
parameter_path='flow_sheet.column.binding_model.adsorption_rate',
73+
lb=1e-3, ub=1e3,
74+
transform='auto',
75+
indices=[1] # modify only the protein (component index 1) parameter
76+
)
77+
78+
optimization_problem.add_variable(
79+
name='desorption_rate',
80+
parameter_path='flow_sheet.column.binding_model.desorption_rate',
81+
lb=1e-3, ub=1e3,
82+
transform='auto',
83+
indices=[1]
84+
)
85+
```
86+
87+
Then, the independent variables $k_{eq}$ and $k_{kin}$ are added. To ensure, that CADET-Process does not try to write
88+
these variables into the CADET-Core model, where they do not have a place, `evaluation_objects` is set to `None`.
89+
90+
```{code-cell} ipython3
91+
optimization_problem.add_variable(
92+
name='equilibrium_constant',
93+
evaluation_objects=None,
94+
lb=1e-4, ub=1e3,
95+
transform='auto',
96+
indices=[1]
97+
)
98+
99+
optimization_problem.add_variable(
100+
name='kinetic_constant',
101+
evaluation_objects=None,
102+
lb=1e-4, ub=1e3,
103+
transform='auto',
104+
indices=[1]
105+
)
106+
```
107+
108+
Lasty, the dependency between the variables is added with the `.add_variable_dependency()` method.
109+
110+
```{code-cell} ipython3
111+
optimization_problem.add_variable_dependency(
112+
dependent_variable="desorption_rate",
113+
independent_variables=["kinetic_constant", ],
114+
transform=lambda k_kin: 1 / k_kin
115+
)
116+
117+
optimization_problem.add_variable_dependency(
118+
dependent_variable="adsorption_rate",
119+
independent_variables=["kinetic_constant", "equilibrium_constant"],
120+
transform=lambda k_kin, k_eq: k_eq / k_kin
121+
)
122+
```

examples/characterize_chromatographic_system/binding_model_parameters.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,30 @@ if __name__ == '__main__':
246246
indices=[1] # modify only the protein (component index 1) parameter
247247
)
248248
249+
optimization_problem.add_variable(
250+
name='desorption_rate',
251+
parameter_path='flow_sheet.column.binding_model.desorption_rate',
252+
lb=1e-3, ub=1e3,
253+
transform='auto',
254+
indices=[1] # modify only the protein (component index 1) parameter
255+
)
256+
257+
optimization_problem.add_variable(
258+
name='equilibrium_constant',
259+
evaluation_objects=None,
260+
lb=1e-4, ub=1e3,
261+
transform='auto',
262+
indices=[1] # modify only the protein (component index 1) parameter
263+
)
264+
265+
optimization_problem.add_variable(
266+
name='kinetic_constant',
267+
evaluation_objects=None,
268+
lb=1e-4, ub=1e3,
269+
transform='auto',
270+
indices=[1] # modify only the protein (component index 1) parameter
271+
)
272+
249273
optimization_problem.add_variable(
250274
name='characteristic_charge',
251275
parameter_path='flow_sheet.column.binding_model.characteristic_charge',
@@ -254,6 +278,18 @@ if __name__ == '__main__':
254278
indices=[1] # modify only the protein (component index 1) parameter
255279
)
256280
281+
optimization_problem.add_variable_dependency(
282+
dependent_variable="desorption_rate",
283+
independent_variables=["kinetic_constant", ],
284+
transform=lambda k_kin: 1 / k_kin
285+
)
286+
287+
optimization_problem.add_variable_dependency(
288+
dependent_variable="adsorption_rate",
289+
independent_variables=["kinetic_constant", "equilibrium_constant"],
290+
transform=lambda k_kin, k_eq: k_eq / k_kin
291+
)
292+
257293
258294
def callback(simulation_results, individual, evaluation_object, callbacks_dir='./'):
259295
comparator = comparators[evaluation_object.name]
@@ -265,6 +301,11 @@ if __name__ == '__main__':
265301
266302
267303
optimization_problem.add_callback(callback, requires=[simulator])
304+
305+
print(optimization_problem.variable_names)
306+
x0 = [1, 1, 1e-2, 1e-3, 10]
307+
ind = optimization_problem.create_individual(x0)
308+
optimization_problem.evaluate_callbacks(ind)
268309
```
269310

270311
```{note}

examples/characterize_chromatographic_system/binding_model_parameters.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,30 @@ def create_comparator(reference):
248248
indices=[1] # modify only the protein (component index 1) parameter
249249
)
250250

251+
optimization_problem.add_variable(
252+
name='desorption_rate',
253+
parameter_path='flow_sheet.column.binding_model.desorption_rate',
254+
lb=1e-3, ub=1e3,
255+
transform='auto',
256+
indices=[1] # modify only the protein (component index 1) parameter
257+
)
258+
259+
optimization_problem.add_variable(
260+
name='equilibrium_constant',
261+
evaluation_objects=None,
262+
lb=1e-4, ub=1e3,
263+
transform='auto',
264+
indices=[1] # modify only the protein (component index 1) parameter
265+
)
266+
267+
optimization_problem.add_variable(
268+
name='kinetic_constant',
269+
evaluation_objects=None,
270+
lb=1e-4, ub=1e3,
271+
transform='auto',
272+
indices=[1] # modify only the protein (component index 1) parameter
273+
)
274+
251275
optimization_problem.add_variable(
252276
name='characteristic_charge',
253277
parameter_path='flow_sheet.column.binding_model.characteristic_charge',
@@ -256,6 +280,18 @@ def create_comparator(reference):
256280
indices=[1] # modify only the protein (component index 1) parameter
257281
)
258282

283+
optimization_problem.add_variable_dependency(
284+
dependent_variable="desorption_rate",
285+
independent_variables=["kinetic_constant", ],
286+
transform=lambda k_kin: 1 / k_kin
287+
)
288+
289+
optimization_problem.add_variable_dependency(
290+
dependent_variable="adsorption_rate",
291+
independent_variables=["kinetic_constant", "equilibrium_constant"],
292+
transform=lambda k_kin, k_eq: k_eq / k_kin
293+
)
294+
259295

260296
def callback(simulation_results, individual, evaluation_object, callbacks_dir='./'):
261297
comparator = comparators[evaluation_object.name]
@@ -268,6 +304,11 @@ def callback(simulation_results, individual, evaluation_object, callbacks_dir='.
268304

269305
optimization_problem.add_callback(callback, requires=[simulator])
270306

307+
print(optimization_problem.variable_names)
308+
x0 = [1, 1, 1e-2, 1e-3, 10]
309+
ind = optimization_problem.create_individual(x0)
310+
optimization_problem.evaluate_callbacks(ind)
311+
271312
# %% [markdown]
272313
# ```{note}
273314
# For performance reasons, the optimization is currently not run when building the documentation.

0 commit comments

Comments
 (0)