Trade studies

Requires the trades extra (pip install "longeron[trades]").

Discrete architecture trade studies on OR-Tools CP-SAT (spike).

Maps a SysML v2 assembly whose part usages are typed by variation definitions (a component catalog) onto a CP-SAT model:

  • variation part usage -> one Boolean selection literal per variant (+ exactly-one); a [4] multiplicity selects homogeneously (all four motors are the same variant – per-index heterogeneous selection is a documented phase-2 item).

  • variant attribute values -> integer variables channeled to the selected variant’s values, in exact fixed-point (per-attribute scale = lcm of the value denominators).

  • derived assembly attributes -> fixed-point arithmetic over those variables: + - * /, constant non-negative integer exponents, max()/min() (native add_max_equality/add_min_equality), and calc def invocations, which are inlined – the invoked calc’s result expression is encoded with the caller’s argument values bound to its parameters (recursively; cycles are refused).

  • assert constraint bodies -> half-reified linear constraints under one named enforcement literal each, so TradeStudy.explain() can ask CP-SAT which requirement subset is sufficient for infeasibility.

Fixed-point error budget (all rounding is one-sided and bounded):

  • float constants and variant values are rounded to seven significant decimal digits (relative error <= 5e-7);

  • division results and rescaled intermediates keep at least six significant digits (relative error <= 1e-5 per operation).

Feasible architectures are enumerated (or optimized) by CP-SAT; every reported Architecture is then re-evaluated exactly by the interpreter (metrics + a verified constraint re-check), so fixed-point rounding can never misreport a design. A mix that CP-SAT’s rounded arithmetic judges feasible but the interpreter refutes is returned with verified=False – the interpreter stays the sole semantic oracle.

What the mapper still refuses – with an AnalysisError naming the innermost unencodable operation – is arithmetic with no exact fixed-point form: sqrt, fractional pow, and if/else conditionals (the real physics of the DeepScout mission layers, examples/deepscout/missions.sysml). The honest pattern there is TradeStudy.all_architectures() / TradeStudy.evaluate(): walk the (small) Cartesian candidate space and let the interpreter evaluate every mix exactly, violations naming the constraints an infeasible mix breaks.

Requires the trades extra: pip install "longeron[trades]" (TradeStudy.evaluate() and TradeStudy.all_architectures() run on the interpreter alone).

class longeron.analysis.trades.Architecture(selection, metrics, verified=True, violations=<factory>)[source]

Bases: object

One component mix, with interpreter-exact metrics.

violations: list[str]

names of the constraints the interpreter found violated (the mix-level answer to “why is this one infeasible?”)

class longeron.analysis.trades.TradeStudy(model, assembly)[source]

Bases: object

Enumerate/optimize variant selections for one assembly definition.

evaluate(selection)[source]

Interpreter-exact metrics for any mix, feasible or not.

selection maps every variation-point name to a variant name; the returned verified flag reports whether all constraints hold. No solver runs – this needs only the interpreter.

Return type:

Architecture

margins(selection)[source]

Numeric constraint margins for one mix (>= 0 iff it holds).

Per constraint name: {"margin", "ok", "text"}. margin follows the standard orientation (lhs <= rhs -> rhs - lhs, lhs >= rhs -> lhs - rhs; strict comparisons use their closure) and is None when the body is not a plain comparison – ok still reports the interpreter’s verdict. text is the constraint body’s source text, so a view can show the requirement threshold next to the achieved margin.

Return type:

dict[str, dict[str, Any]]

all_architectures()[source]

Every candidate mix (the full Cartesian product), exact metrics.

Unlike enumerate(), infeasible mixes are included (with verified=False) – the raw material for views that show the frontier inside the whole candidate space.

Return type:

list[Architecture]

enumerate()[source]

All feasible architectures, interpreter-verified.

Return type:

list[Architecture]

explain()[source]

[] when feasible; else constraint names sufficient for UNSAT.

Return type:

list[str]

class longeron.analysis.trades.VariationPoint(name, count, variants)[source]

Bases: object

A part usage typed by a variation definition.

longeron.analysis.trades.pareto(architectures, minimize=(), maximize=())[source]

The non-dominated subset under the given objectives.

Return type:

list[Architecture]