Package architecture¶
This page is for developers. It shows the modules of elicito,
the imports between them, and the cohesion of each subpackage.
The graph uses only the imports that run when a module loads.
The package facade elicito/__init__.py imports everything,
so it is not part of the graph.
The parse helpers are a copy of those in
tests/unit/test_architecture.py. Keep the two copies the same.
Core modules¶
Entry points for the user
specs: the constructors of the user specification, such asel.model,el.parameter,el.hyper,el.target,el.expert,el.optimizerandel.trainer.elicit: theElicitclass. It checks the input, and it has the methodsfit,sample,saveandload.
Building blocks. There is one block for each concept in the workflow figure.
parameters/: the priors of the model parameters.parametriclearns independent parametric priors.deeplearns a joint prior with a normalizing flow fromnetworks.priorsbuilds the trainable prior model.initializers/: the start values of the hyperparameters. The methods areexact,sampling(random, lhs, sobol),warmstartandcmaes.specholdsel.initializer.optimizers/: the fit.sgdtrains with a gradient-based optimizer, andcmaesruns a CMA-ES search.searchholds the objective and the box that the searches share.models: the forward pass, from prior samples through the generative model to the elicited statistics.targets: the target quantities and the elicited statistics.losses: the discrepancy losses, such asMMD2andL2, and the weighted total loss.
In parameters/ and initializers/, the module methods holds the
protocol that each method implements, and the registry of the methods.
Support modules
utils: the expert data, the parallel settings, and small helpers._storage: saving an eliobj to a file, and reading it back._checks: the checks of the user input toElicit._outputs: thexr.DataTreeineliobj.results._progress: the progress table during training and initialization.plots: the plots of the results.typesandexceptions: the shared types and exceptions. They import no other elicito module. With_progress, they form layer 0.
Workflow of the Elicit object¶
The figure follows the conceptual workflow in the tutorials.
Each box names the concept, the elicito function that does the work,
and, in italics, the specification that the user writes.
The upper panel is one run of Elicit.workflow(seed).
The loop repeats for each epoch.
The lower strip shows the public methods of the Elicit object.
Layers¶
Each node is a subpackage or a top-level module. An arrow points from a module to a module that it imports. A node sits one layer above the highest node that it imports. Layer 0 imports no other elicito module.
Dependency structure matrix¶
A dark cell in row A and column B means: module A imports module B. The blue lines separate the subpackages. The order follows the layers, so all cells lie below the diagonal. A cell above the diagonal would show an import cycle.
Cohesion and coupling¶
The table counts the module imports for each node of the layer plot.
- internal: imports between the modules of the node.
- outgoing: imports from the node to other nodes.
- incoming: imports from other nodes into the node.
- cohesion is internal / (internal + outgoing). A high value means that the modules of the node work mostly together.
- instability is outgoing / (incoming + outgoing), after Robert C. Martin. A value of 0 means that other nodes depend on it, and it depends on none.
| node | modules | internal | outgoing | incoming | cohesion | instability |
|---|---|---|---|---|---|---|
_progress |
1 | 0 | 0 | 4 | - | 0.00 |
_storage |
1 | 0 | 0 | 1 | - | 0.00 |
exceptions |
1 | 0 | 0 | 4 | - | 0.00 |
types |
1 | 0 | 0 | 24 | - | 0.00 |
_outputs |
1 | 0 | 1 | 1 | - | 0.50 |
losses |
1 | 0 | 1 | 4 | - | 0.20 |
parameters |
8 | 13 | 6 | 25 | 0.68 | 0.19 |
targets |
1 | 0 | 1 | 1 | - | 0.50 |
models |
1 | 0 | 5 | 5 | - | 0.50 |
specs |
1 | 0 | 3 | 1 | - | 0.75 |
optimizers |
4 | 4 | 19 | 14 | 0.17 | 0.58 |
utils |
1 | 0 | 4 | 2 | - | 0.67 |
_checks |
1 | 0 | 5 | 1 | - | 0.83 |
initializers |
9 | 20 | 27 | 1 | 0.43 | 0.96 |
plots |
1 | 0 | 4 | 0 | - | 1.00 |
elicit |
1 | 0 | 12 | 0 | - | 1.00 |
Stable dependencies¶
A good instability value depends on the role of the node.
A base node, such as types, has many incoming imports.
Its instability should be near 0, because many nodes break if it changes.
A top node, such as elicit, has no incoming imports.
Its instability can be near 1, because you can change it freely.
The Stable Dependencies Principle of Robert C. Martin gives a rule to check: a node should import only nodes with an instability that is not higher. The table lists each import that breaks this rule. Such an import makes a node depend on a node that changes more often.
No import goes to a less stable node.