Source code for cosapp.drivers.metasystembuilder
from collections import OrderedDict
from typing import Any, Dict, List, Set, Type, Union, Optional
from cosapp.recorders import DataFrameRecorder
from cosapp.systems import MetaSystem
from cosapp.utils.surrogate_models import ResponseSurface
from cosapp.drivers.driver import Driver
from cosapp.drivers.lineardoe import LinearDoE
from cosapp.drivers.nonlinearsolver import NonLinearSolver
# TODO
# [ ] Quid for vector variables
# [ ] Simplify the builder by using inputs and outputs of the targeted system.
[docs]
class MetaSystemBuilder(Driver):
__slots__ = ('responses', 'model_type', '_metasystem')
def __init__(
self,
name: str,
owner: Optional["cosapp.systems.System"] = None,
**kwargs
) -> None:
"""Initialize a driver
Parameters
----------
name: str, optional
Name of the `Driver`.
owner: System, optional
:py:class:`~cosapp.systems.system.System` to which this driver belong; defaults to `None`.
**kwargs:
Additional keywords arguments forwarded to base class.
"""
super().__init__(name, owner, **kwargs)
self.responses = set() # type: Set[str]
self.model_type = ResponseSurface # type: Type
self._metasystem = None # type: cosapp.systems.MetaSystem
self.add_child(LinearDoE("doe"))
self.doe.add_child(NonLinearSolver("solve"))
[docs]
def compute(self):
includes = list(self.doe.input_vars)
includes.extend(self.responses)
self.doe.add_recorder(DataFrameRecorder(raw_output=True, includes=includes))
self.doe.run_once()
class MyMeta(MetaSystem):
def setup(self, model_type=ResponseSurface, ref_model=None):
self._default_model = model_type
if ref_model:
self.inputs = OrderedDict(ref_model.inputs)
self.outputs = OrderedDict(ref_model.outputs)
self._metasystem = MyMeta(
"meta",
self.doe.recorder.export_data(),
model_type=self.model_type,
ref_model=self.owner,
)
[docs]
def add_input_var(
self,
definition: Union[str, Dict[str, Any]],
lower: float = None,
upper: float = None,
count: int = 2,
):
self.doe.add_input_var(definition, lower, upper, count)
[docs]
def add_response(self, name: Union[str, List[str]]):
if not isinstance(name, (str, list)):
raise TypeError(
f"'name' should be a string or a list of strings; got {type(name).__name__}."
)
def add_unique_response_var(name: str):
self.check_owner_attr(name)
self.responses.add(name)
if isinstance(name, str):
add_unique_response_var(name)
else:
for n in name:
if isinstance(n, str):
add_unique_response_var(n)
else:
raise TypeError(
f"name list should only contain strings; got {type(n).__name__}."
)