M0 interpretations¶
Populations of individuals, Annex-A sequences, and roll-ups over the actual population — see the design document for the semantics and the adopted decisions, and tutorial 09 for a worked tour.
longeron.m0¶
M0 interpretations: populations of identified individuals over a model.
Where instantiate() produces one
anonymous deep instance, this module produces an Interpretation:
a population of Individual runtime instances with stable
identities (qname#index paths), built under a strategy
("nominal" follows declared multiplicities and variant order;
"random" draws seeded population sizes, variant choices, and unvalued
enum/Boolean attribute values), with KerML Annex A sequence semantics
(Interpretation.sequences()) and expression roll-ups over the
actual population (Interpretation.rollup() – sum(rotors.mass)
adds the four real rotor individuals instead of hand-encoding
4.0 * rotorMass at M1).
The same representation covers dynamic semantics: every contiguous state
activation recorded by longeron.replay.record_timeline() is an
occurrence with a lifetime, and from_timeline() turns it into an
occurrence Individual (start/end/duration slots) in an
ordinary Interpretation – simulation traces and static
populations share one M0 story. from_architecture() reads a trade
study’s Architecture as a partial
interpretation (the variant selection), so M0 roll-ups can be checked
against the metrics the trades machinery computes at M1.
Concepts follow pymbe’s interpretation package (random interpretations,
Annex A atoms, calc roll-ups) but individuals stay runtime values – the
M1 model is never mutated.
The OMG Systems Modeling API has no M0 payload; Interpretation.
to_dict() is a deliberate longeron extension (JSON-able, ids included) and
is not part of to_api_json.
- class longeron.m0.Individual(id, type_name, definition=None)[source]¶
Bases:
InstanceAn M0 individual: a runtime
Instancewith a stable identity.idis aqname#indexpath (Pkg::Quad#0.rotors#2); occurrence individuals fromfrom_timeline()useqname@kand carrystart/end/durationslots.- to_json()[source]¶
Alias for
to_dict()– the lossless case-recorder seam.OpenMDAO’s
make_serializabletriesto_jsonfirst when a recorded value is not JSON-native; without this hook a recorded entity case silently degrades to the class-name string'Individual'(see the mdao-objects design, finding 2). Equal individuals produce equal dicts, so recorded cases compare stably.
- class longeron.m0.Interpretation(source, strategy, seed, root, selection=<factory>, gaps=<factory>, _interpreter=None, _bindings=<factory>, _pins=<factory>)[source]¶
Bases:
objectA population of M0 individuals for one M1 element.
- strategy: Literal['nominal', 'random', 'trace']¶
‘trace’: replayed by
from_timeline()
- selection: dict[str, str]¶
variant chosen per variation-typed feature path (per-index for heterogeneous random populations, e.g.
motors#2)
- individuals(classifier=None)[source]¶
All individuals (root first, depth-first), optionally filtered to those conforming to
classifier(a resolvable qualified name; occurrence individuals match on their recorded type name).- Return type:
- sequences(feature_path)[source]¶
KerML Annex A sequences for a (dotted) feature path.
A feature is interpreted as a set of sequences whose prefix is an individual of the featuring type:
sequences("rotors")yields(quad, rotor_i)tuples,sequences("rotors.mass")yields(quad, rotor_i, 0.06)– nested features are longer sequences.
- rollup(expr)[source]¶
Evaluate an expression over the actual population.
Feature references resolve against the root individual’s slots, so multi-individual features yield the real value sequences and aggregates aggregate over them:
rollup("sum(rotors.mass)")adds the four rotor individuals’ masses. A plain feature name evaluates that feature’s declared M1 expression instead (which fails, honestly, when the M1 expression leans on the homogeneous4.0 * xconvention).- Return type:
- longeron.m0.Strategy¶
the population-construction strategies
interpret()accepts (Interpretation.strategyadditionally records"trace"for interpretations replayed from a timeline byfrom_timeline())alias of
Literal[‘nominal’, ‘random’]
- longeron.m0.from_architecture(study, architecture)[source]¶
Read a trade-study
Architectureas the partial M0 interpretation it is: the architecture pins every variation point’s variant, the multiplicities populate the individuals (motors : MotorChoice[4]becomes four individuals of the selected variant), and roll-ups over those individuals reproduce the metrics the trades machinery computed at M1.- Return type:
- longeron.m0.from_timeline(timeline, interpreter=None, *, source='<execution>')[source]¶
Turn a recorded
Timelineinto an interpretation of occurrence individuals.Every contiguous activation of a state becomes one occurrence
Individual(idqname@k) withstart/end/durationslots; the root individual spans the whole execution and owns them in activation order underoccurrences. Roll-ups work as usual:rollup("sum(occurrences.duration)").- Return type:
- longeron.m0.interpret(model, element=None, *, strategy='nominal', seed=None, bindings=None, selection=None)[source]¶
Build an M0 interpretation of a part/item definition or usage.
strategy="nominal"follows declared multiplicities (exact bounds expand fully, ranges take their lower bound – matchingInterpreter.instantiate) and picks the first declared variant at unresolved variation points.strategy="random"draws population sizes uniformly within multiplicity bounds (unbounded uppers capped atlower + 3), chooses variants per individual, and samples unvalued enum/Boolean attributes from their literal domains – all from one seeded generator, so equal seeds reproduce equal populations.bindingsoverride root feature values by name;selectionpins variation-typed feature paths ({"motors": "emax2306"}) under any strategy. Evaluation failures degrade toNoneand are recorded inInterpretation.gaps.- Return type: