Quickstart Guide¶
Note
This library is an extension for the RTC-Tools library. These instructions assume some basic familarity with RTC-Tools.
Even though rtc-tools-meta allows for powerful aggregation of rtc-tools
models, the api is relatively simple. This is because it is able to reuse all of
the configuration of the sub-models. This guide shows the steps to get
rtc-tools-meta working for your models.
1. Inherit from MetaMixin¶
If you are familiar with the rtc-tools api, this one will come as no
surprise to you. Every rtc-tools optimization problem that you want to link
into your meta optimization problem must inherit from MetaMixin. Don’t
worry, you can still run your models independently like normal even after you
inherit from it- it only takes effect on your model while the meta optimization
problem is running. You can inherit from MetaMixin like this:
from rtc_tools_meta.meta_mixin import MetaMixin # First import the mixin
class MyOptimizationProblem(
MetaMixin,
# Other mixins (ModelicaMixin, etc.)
)
2. Define the MetaOptimizationProblem¶
This class contains all the guts for aggregation and deaggregation. We inherit from this class to build meta-model classes. Note that submodels may also be other MetaOptimizationProblem classes- just make sure you map the interfaces correctly. Here is how that is done.
First we get the dependencies imported:
# Useful for specifying path to submodels
from pathlib import Path
# Needed to define meta_objective
import casadi as ca
# Our meta model inherits from this class
from rtc_tools_meta.meta_optimization_problem import MetaOptimizationProblem
# A handy function to make referencing submodels easy
from rtc_tools_meta.util import collect_model_instance
Next, we define a new class:
class ModelAB(MetaOptimizationProblem):
"""Meta Problem Optimizing ModelA and ModelB"""
The bulk of the meta optimization problem configuration is in defining the
attributes submodels, variable_mappings, and meta_objective. Here
are the details about what these should look like:
-
MetaOptimizationProblem.submodels Dictionary of submodels
This variable is where we store the submodel instances. The models are indexed by a unique short name. For example:
# Meta Problem Optimizing ModelA and ModelB submodels = { "ModelA": collect_model_instance('ModelA', path_to_a), "ModelB": collect_model_instance('ModelB', path_to_b), }
Return type: Dict[str,OptimizationProblem]
-
MetaOptimizationProblem.variable_mappings Mappings that constrain variables in separate submodels to be equal
To define how submodels interact with each other, we set
variable_mappingsequal to a list of 3-tuples. The 3-tuples have the structure (var1, var2, sign). For example:# Meta Problem Optimizing ModelA and ModelB variable_mappings = [ ( "ModelA::some_variable", "ModelB::another_variable", "-", # Either "-" (if vars are equal) or "+" (if they sum to 0) ) ]
Return type: List[Tuple[str,str,str]]
-
MetaOptimizationProblem.meta_objective()[source] Symbolic expression to be minimized
For example, here is a quadratic minimization objective:
def meta_objective(self): return ca.sum1(self.states_in("ModelA::var_name")) ** 2.0
Return type: MX
3. Run your problem¶
Once everything is properly connected, just run the optimize() method of
your highest level MetaOptimizationProblem class- the library will do the
rest. When it completes, you can import the results of the submodels in their
respective output folders. Here is an example of all the code together:
# Useful for specifying path to submodels
from pathlib import Path
# Needed to define meta_objective
import casadi as ca
# Our meta model inherits from this class
from rtc_tools_meta.meta_optimization_problem import MetaOptimizationProblem
# A handy function to make referencing submodels easy
from rtc_tools_meta.util import collect_model_instance
class ModelAB(MetaOptimizationProblem):
"""Meta Problem Optimizing ModelA and ModelB"""
submodels = {
"ModelA": collect_model_instance('ModelA', path_to_a),
"ModelB": collect_model_instance('ModelB', path_to_b),
}
variable_mappings = [
(
"ModelA::some_variable",
"ModelB::another_variable",
"-",
)
]
def meta_objective(self):
return ca.sum1(self.states_in("ModelA::var_name")) ** 2.0
if __name__ == "__main__":
problem = ModelAB()
problem.optimize()