Requirement Satisfaction Evaluation v0.9.0 Labs
Experimental feature
This example uses experimental unit conversion functionality. Enable with
experimental_quantities=True.
This example evaluates whether each RequirementUsage in a model is satisfied.
The model defines reusable requirement def declarations parameterized by a
subject and typed attributes, declares them on part def Bicycle, and redefines
their attributes on each variant in a variation part def. The bicycle variants cover
three outcomes: passing, failing a requirement, and a case where a violated assume
constraint makes the requirement not apply.
Model Structure
RequirementSatisfactionExample
├── Bicycle
│ ├── requirement massOk (mass <= 12 kg)
│ └── requirement wheelOk (600 <= wheelDiameter <= 800 mm)
├── TandemBike :> Bicycle
│ ├── requirement massOk (mass <= 25 kg)
│ └── requirement wheelOk (600 <= wheelDiameter <= 800 mm)
└── BicycleSelection
├── roadBike : Bicycle (mass = 9 kg, wheelDiameter = 700 mm)
├── heavyBike : Bicycle (mass = 18 kg, wheelDiameter = 750 mm)
├── impossibleBike : TandemBike (mass = 20 kg, wheelDiameter =-500 mm)
└── ChildBikes
└── smallBike : Bicycle (mass = 7 kg, wheelDiameter = 500 mm)
Each variant binds its own subject explicitly via a scope override (requirement
:>> massOk { subject bike = roadBike; }). Requirements declared on part def
Bicycle and part def TandemBike are blueprints: their expressions reference each
definition’s own parameters rather than the features of a concrete usage, so they cannot
be evaluated.
Assumed and Required Constraints
Each requirement def is built from two parts: a require constraint that must
hold for the requirement to be satisfied, and an optional assume constraint that
guards when the requirement applies. If the assume constraint is False, the
requirement does not apply, and the evaluator reports True without checking the
require constraint.
requirement def MassLimit {
subject bike : Bicycle;
attribute limit : MassValue;
assume constraint { bike.mass > 0 [kg] }
require constraint { bike.mass <= limit }
}
WheelSizeRange follows the same pattern, with wheelDiameter > 0 [mm] as its
assume and minDiameter <= wheelDiameter <= maxDiameter as its require.
The impossibleBike variant exercises the assume guard. Its wheelDiameter = -500
[mm] violates bike.wheelDiameter > 0 [mm], so wheelOk evaluates to True
even though -500 [mm] is well outside [600, 800] [mm].
Warning
A passing requirement does not always mean the require constraint holds. it may mean the assume constraint failed and the requirement did not apply.
When auditing results, verify that the assume conditions actually held.
Selecting Requirements to Evaluate
A RequirementUsage whose owning_type is a Definition is a blueprint and is
excluded. Requirements owned by another Usage (a variant part, in this model)
are bound to that owning usage and can access its features; each variant in this model
also supplies an explicit subject binding via scope override, so evaluation can
proceed. Composite sub-requirements nested inside another RequirementUsage are also
skipped because the outer requirement’s verdict already aggregates them:
requirements = [
req
for req in model.elements(syside.RequirementUsage, include_subtypes=True)
if req.document.document_tier is syside.DocumentTier.Project
and isinstance(req.owning_type, syside.Usage)
and (
not req.is_composite or not isinstance(req.owning_type, syside.RequirementUsage)
)
]
Evaluating a Requirement
Compiler.evaluate reduces a requirement to a
boolean, honoring the assume guard, with the subject and attribute redefinitions
resolved from the usage’s own scope:
value, report = compiler.evaluate(
req, stdlib=STANDARD_LIBRARY, experimental_quantities=True
)
The experimental_quantities=True flag enables automatic unit conversion, so a
constraint comparing [kg] to [kg] or [mm] to [mm] is evaluated
numerically.
Concepts Used
SysML v2 requirement concepts:
Concept |
Syntax |
Description |
|---|---|---|
Requirement definition |
|
Reusable requirement parameterized by a subject and attributes |
Subject parameter |
|
The element being constrained; bound at the usage site |
Required constraint |
|
Boolean expression that must hold for the requirement to be satisfied |
Assumed constraint |
|
Precondition under which the requirement applies |
Variation / variant |
|
A definition with discrete alternatives, each a concrete |
Redefinition |
|
Redefines an inherited feature (here, to bind |
Quantity comparison |
|
Compares quantity-typed attributes; with |
Syside API:
API |
Purpose |
|---|---|
Evaluates a |
|
Iterates over semantic elements, optionally including subtypes |
|
The |
Example Model
package RequirementSatisfactionExample {
private import ScalarValues::*;
private import SI::*;
requirement def MassLimit {
subject bike : Bicycle;
attribute limit : MassValue;
assume constraint { bike.mass > 0 [kg] }
require constraint { bike.mass <= limit }
}
requirement def WheelSizeRange {
subject bike : Bicycle;
attribute minDiameter : LengthValue;
attribute maxDiameter : LengthValue;
assume constraint { bike.wheelDiameter > 0 [mm] }
require constraint {
(bike.wheelDiameter >= minDiameter)
and (bike.wheelDiameter <= maxDiameter)
}
}
// Requirements declared on `Bicycle` and `TandemBike` are blueprints:
// their expressions reference each definition's own parameters rather
// than the features of a concrete usage, so they cannot be evaluated.
part def Bicycle {
attribute mass : MassValue;
attribute wheelDiameter : LengthValue;
requirement massOk : MassLimit {
attribute :>> limit default 12 [kg];
}
requirement wheelOk : WheelSizeRange {
attribute :>> minDiameter default 600 [mm];
attribute :>> maxDiameter default 800 [mm];
}
}
part def TandemBike :> Bicycle {
requirement :>> massOk {
attribute :>> limit = 25 [kg];
}
}
variation part def BicycleSelection {
variant part roadBike : Bicycle {
attribute :>> mass = 9 [kg];
attribute :>> wheelDiameter = 700 [mm];
requirement :>> massOk { subject bike = roadBike; }
requirement :>> wheelOk { subject bike = roadBike; }
}
variant part heavyBike : Bicycle {
attribute :>> mass = 18 [kg];
attribute :>> wheelDiameter = 750 [mm];
requirement :>> massOk { subject bike = heavyBike; }
requirement :>> wheelOk { subject bike = heavyBike; }
}
variant part impossibleBike : TandemBike {
attribute :>> mass = 20 [kg];
requirement :>> massOk { subject bike = impossibleBike; }
// Unrealistic value
attribute :>> wheelDiameter = -500 [mm];
// Requirement check passes as assume constraint is violated
requirement :>> wheelOk { subject bike = impossibleBike; }
}
variation part def ChildBikes {
variant part smallBike : Bicycle {
attribute :>> mass = 7 [kg];
attribute :>> wheelDiameter = 500 [mm];
requirement :>> massOk { subject bike = smallBike; }
requirement :>> wheelOk { subject bike = smallBike; }
}
}
}
}
Example Script
import pathlib
import syside
EXAMPLE_DIR = pathlib.Path(__file__).parent
MODEL_FILE_PATH = EXAMPLE_DIR / "example_model.sysml"
STANDARD_LIBRARY = syside.Environment.get_default().lib
def main() -> None:
(model, _) = syside.load_model([MODEL_FILE_PATH], warnings_as_errors=True)
compiler = syside.Compiler()
# Skip requirements owned by a `Definition` (expressions reference
# the definition's own parameters) and composites within another
# `RequirementUsage` (already folded into the parent's verdict).
requirements = [
req
for req in model.elements(
syside.RequirementUsage, include_subtypes=True
)
if req.document.document_tier is syside.DocumentTier.Project
and isinstance(req.owning_type, syside.Usage)
and (
not req.is_composite
or not isinstance(req.owning_type, syside.RequirementUsage)
)
]
for req in requirements:
value, report = compiler.evaluate(
req, stdlib=STANDARD_LIBRARY, experimental_quantities=True
)
if report.fatal or not isinstance(value, bool):
marker = "[ ?? ]"
else:
marker = "[ OK ]" if value else "[FAIL]"
print(f" {marker} {req}")
if __name__ == "__main__":
main()
Output
[ OK ] RequirementSatisfactionExample::BicycleSelection::roadBike::massOk
[ OK ] RequirementSatisfactionExample::BicycleSelection::roadBike::wheelOk
[FAIL] RequirementSatisfactionExample::BicycleSelection::heavyBike::massOk
[ OK ] RequirementSatisfactionExample::BicycleSelection::heavyBike::wheelOk
[ OK ] RequirementSatisfactionExample::BicycleSelection::impossibleBike::massOk
[ OK ] RequirementSatisfactionExample::BicycleSelection::impossibleBike::wheelOk
[ OK ] RequirementSatisfactionExample::BicycleSelection::ChildBikes::smallBike::massOk
[FAIL] RequirementSatisfactionExample::BicycleSelection::ChildBikes::smallBike::wheelOk
Download
Download this example here.