-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dev(init): adding all source code and documentation (#5)
* dev(init): adding all source code and documentation
- Loading branch information
Showing
34 changed files
with
5,038 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# Custom | ||
todo.txt | ||
amisc_* | ||
|
||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.md-grid { | ||
max-width: 1440px; | ||
} | ||
|
||
:root > * { | ||
--md-code-hl-keyword-color: #842e21; | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,65 @@ | ||
Coming soon | ||
## Specifying model inputs and outputs | ||
Coming soon. | ||
|
||
## Defining a component | ||
Coming soon. | ||
|
||
## Making a model wrapper function | ||
The examples in the [tutorial](tutorials.md) use the simple function call signatures `ret = func(x)`, where `x` is an `np.ndarray` and | ||
`ret` is a dictionary with the required `y=output` key-value pair. If your model must be executed outside of Python | ||
(such as in a separate `.exe` file), then you can write a Python wrapper function with the same call signature as above | ||
and make any external calls you need inside the function (such as with `os.popen()`). You then pass the wrapper function | ||
to `ComponentSpec` and `SystemSurrogate`. | ||
|
||
!!! Note "Requirements for your wrapper function" | ||
- First argument `x` must be an `np.ndarray` of the model inputs whose **last** dimension is the number of inputs, i.e. `x.shape[-1] = x_dim`. | ||
- You can choose to handle as many other dimensions as you want, i.e. `x.shape[:-1]`. The surrogate will handle the same number | ||
of dimensions you give to your wrapper function (so that `model(x)` and `surrogate(x)` are functionally equivalent). We recommend you handle at least | ||
1 extra dimension, i.e. `x.shape = (N, x_dim)`. So your wrapper must handle `N` total sets of inputs at a time. The easiest way is to just | ||
write a for loop over `N` and run your model for a single set of inputs at a time. | ||
- Your wrapper function must expect the `x_dim` inputs in a specific order according to how you defined your system. All | ||
system-level exogenous inputs (i.e. those in `system.exo_vars`) must be first and in the order you specified for | ||
`ComponentSpec(exo_in=[first, second, ...])`. All coupling inputs that come from the outputs of other models are next. | ||
Regardless of what order you chose in `ComponentSpec(coupling_in=[one, two, three,...]`, your wrapper **must** expect them | ||
in _sorted_ order according to `system.coupling_vars`. For example, if `system.coupling_vars = [a, b, c]` and | ||
`comp = ComponentSpec(wrapper, coupling_in=[c, a], exo_in=[d, e], coupling_out=[f])`, then `x_dim = 4` and your `wrapper` function | ||
should expect the inputs in `x` to be ordered as `[d, e, a, c]`. | ||
- If you want to pass in model fidelity indices (see $\alpha$ in [theory](theory.md) for details), they must be in the form of a `tuple`, | ||
and your wrapper function should accept the `alpha=...` keyword argument. Specifying `alpha` allows managing a hierarchy of modeling fidelities, if applicable. | ||
- You can pass any number of additional positional arguments. Specify these with `ComponentSpec(model_args=...)`. | ||
- You can pass any number of keyword arguments. Specify these with `ComponentSpec(model_kwargs=...)`. | ||
- If you want to save and keep track of the full output of your model (i.e. if it writes result files to disk), then | ||
you can specify `ComponentSpec(save_output=True)`. When you do this, you must also specify `SystemSurrogate(..., save_dir='path/to/save/dir')`. | ||
You will then get a folder called `save_dir/amisc_timestamp/components/<your_model_name>`. This folder will be passed to your | ||
wrapper function as the keyword argument `output_dir=<your_model_dir>`. Make sure your `wrapper` accepts this keyword (no need to specify it in `ComponentSpec(model_kwargs=...)`; this is done automatically). | ||
You can then have your model write whatever it wants to this folder. You **must** then pass back the names of the files | ||
you created via `ret=dict(files=[your output files, ...])`. The filenames must be in a list and match the order in | ||
which the samples in `x` were executed by the model. | ||
- To assist the adaptive training procedure, you can also optionally have your model compute and return its computational cost via | ||
`ret=dict(cost=cpu_cost)`. The computational cost should be expressed in units of seconds of CPU time (not walltime!) for _one_ model evaluation. | ||
If your model makes use of `n` CPUs in parallel, then the total CPU time would be `n` times the wall clock time. | ||
- The return dictionary of your wrapper can include anything else you want outside of the three fields `(y, files, cost)` discussed here. | ||
Any extra return values will be ignored by the system. | ||
|
||
!!! Example | ||
```python | ||
def wrapper_func(x, alpha, *args, output_dir=None, **kwargs): | ||
print(x.shape) # (..., x_dim) | ||
|
||
# Your code here, for example: | ||
output = x ** 2 | ||
output_files = ['output_1.json', 'output2.json', ...] | ||
cpu_time = 42 # seconds for one model evaluation | ||
|
||
ret = dict(y=output, files=output_files, cost=cpu_time) | ||
|
||
return ret | ||
``` | ||
|
||
!!! Warning | ||
Always specify the model at a _global_ scope, i.e. don't use `lambda` or nested functions. When saving to | ||
file, only a symbolic reference to the function signature will be saved, which must be globally defined | ||
when loading back from that save file. | ||
|
||
## Putting it all together | ||
Coming soon. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
window.MathJax = { | ||
tex: { | ||
inlineMath: [['$', '$'], ["\\(", "\\)"]], | ||
displayMath: [["\\[", "\\]"]], | ||
processEscapes: true, | ||
processEnvironments: true | ||
}, | ||
options: { | ||
ignoreHtmlClass: ".*|", | ||
processHtmlClass: "arithmatex" | ||
} | ||
}; | ||
|
||
document$.subscribe(() => { | ||
MathJax.typesetPromise() | ||
}) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
::: amisc.component | ||
options: | ||
members_order: source |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
::: amisc.interpolator | ||
options: | ||
filters: [""] | ||
members_order: source |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
The `amisc` package takes an object-oriented approach to building a surrogate of a multidisciplinary system. From the | ||
bottom up, you have: | ||
|
||
- **variables** that serve as inputs and outputs for the models, | ||
- **interpolators** that define a specific input → output mathematical relationship to interpolate a function, | ||
- **components** that wrap a model for a single discipline, and a | ||
- **system** that defines the connections between components in a multidisciplinary system. | ||
|
||
The variables, interpolators, and components all have abstract base classes, so that the **system** is ultimately | ||
independent of the specific models, interpolation methods, or underlying variables. As such, the primary top-level object | ||
that users of the `amisc` package will interact with is the `SystemSurrogate`. | ||
|
||
!!! Note | ||
There are already pretty good implementations of the other abstractions that most users will not need to worry about, | ||
but they are provided in this API reference for completeness. The abstractions allow new interpolation | ||
(i.e. function approximation) methods to be implemented if desired, such as neural networks, kriging, etc. | ||
|
||
Here is a class diagram summary of this workflow: | ||
|
||
``` mermaid | ||
classDiagram | ||
namespace Core { | ||
class SystemSurrogate { | ||
+list[BaseRV] exo_vars | ||
+list[BaseRV] coupling_vars | ||
+int refine_level | ||
+fit() | ||
+predict(x) | ||
+sample_inputs(size) | ||
+insert_component(comp) | ||
} | ||
class ComponentSurrogate { | ||
<<abstract>> | ||
+IndexSet index_set | ||
+IndexSet candidate_set | ||
+list[BaseRV] x_vars | ||
+dict[str: BaseInterpolator] surrogates | ||
+dict[str: float] misc_coeff | ||
+predict(x) | ||
+activate_index(alpha, beta) | ||
+add_surrogate(alpha, beta) | ||
+update_misc_coeff() | ||
} | ||
class BaseInterpolator { | ||
<<abstract>> | ||
+tuple beta | ||
+list[BaseRV] x_vars | ||
+np.ndarray xi | ||
+np.ndarray yi | ||
+set_yi() | ||
+refine() | ||
+__call__(x) | ||
} | ||
} | ||
class SparseGridSurrogate { | ||
+np.ndarray x_grids | ||
+dict xi_map | ||
+dict yi_map | ||
+get_tensor_grid(alpha, beta) | ||
} | ||
class LagrangeInterpolator { | ||
+np.ndarray x_grids | ||
+np.ndarray weights | ||
+get_grid_sizes() | ||
+leja_1d() | ||
} | ||
class BaseRV { | ||
<<abstract>> | ||
+tuple bounds | ||
+str units | ||
+float nominal | ||
+pdf(x) | ||
+sample(size) | ||
} | ||
class UniformRV { | ||
+str type | ||
+get_uniform_bounds(nominal) | ||
} | ||
SystemSurrogate o-- "1..n" ComponentSurrogate | ||
ComponentSurrogate o-- "1..n" BaseInterpolator | ||
direction LR | ||
ComponentSurrogate <|-- SparseGridSurrogate | ||
BaseInterpolator <|-- LagrangeInterpolator | ||
SparseGridSurrogate ..> LagrangeInterpolator | ||
BaseRV <|-- UniformRV | ||
``` | ||
Note how the `SystemSurrogate` aggregates the `ComponentSurrogate`, which aggregates the `BaseInterpolator`. In other words, | ||
interpolators can act independently of components, and components can act independently of systems. All three make use | ||
of the random variables (these connections and some RVs are not shown for visual clarity). Currently, the only underlying surrogate | ||
method that is implemented here is Lagrange polynomial interpolation (i.e. the `LagrangeInterpolator`). If one wanted | ||
to use neural networks instead, the only change required is a new implementation of `BaseInterpolator`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
::: amisc.system |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Package utilities | ||
|
||
::: amisc.utils |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
::: amisc.rv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Coming soon. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,26 @@ | ||
Coming soon | ||
## Single component example | ||
Here is an example of interpolating a simple quadratic function. | ||
```python title="amisc.examples.tutorial.py" | ||
--8<-- "amisc/examples/tutorial.py:single" | ||
``` | ||
|
||
## Two component system | ||
Here is a simple example of a two-component multidisciplinary system. | ||
```python title="amisc.examples.tutorial.py" | ||
--8<-- "amisc/examples/tutorial.py:simple" | ||
``` | ||
The first component computes $y=x\sin(\pi x)$. The second component takes the output of the first and computes | ||
$z=1 / (1 + 25y^2)$. The system-level input is $x$ and the system-level outputs are $y$ and $z$. | ||
|
||
!!! Note | ||
Each component always locally returns a dictionary with the output saved as `y=value`. This is not to be confused with the | ||
_system-level_ `y` variable in this example. | ||
|
||
## Fire detection satellite | ||
Here is an example of a three-component fire detection satellite system from [Chauduri (2018)](https://dspace.mit.edu/handle/1721.1/117036). | ||
```python title="amisc.examples.tutorial.py" | ||
--8<-- "amisc/examples/tutorial.py:fire_sat" | ||
``` | ||
We first generate a test set using the ground truth model predictions (and filter any bad values out). Then we train the | ||
surrogate in 10 iterations, and finally plot some results. Here is the output of `plot_slice()`: | ||
![Fire satellite system results](assets/fire_sat.png) |
Oops, something went wrong.