Module 8: Variability & Configuration
How to define variation points, declare alternative variants, and configure product lines — enabling a single model to capture an entire family of system configurations.
KerML → SysML: Variability Concepts
SysML v2 variability is built on KerML’s usage variation and variant membership mechanisms. A variation usage declares a point of variability — a feature that must be bound to exactly one of its allowed alternatives. Each variant within that variation is a distinct membership option. At the KerML level, these are modelled through feature membership and subsetting relationships on usages.
| SysML v2 concept (L2) | Underlying KerML construct (L1) | What SysML adds |
|---|---|---|
variation (on a usage) | Usage with isVariation = true | Marks a feature as a variation point; must be resolved to exactly one variant in any complete configuration |
variant | VariantMembership (a kind of OwningMembership) | Declares a named alternative within a variation point; each variant subsets the variation usage |
variation part def | PartDefinition with isVariation = true | A definition whose usages are inherently variation points — every usage must be resolved |
variant (in a variation def) | VariantMembership owning a usage | A usage that serves as one option within a variation definition |
| Configuration binding | BindingConnector resolving a variation to a specific variant | Fixes the choice; produces a fully resolved product instance |
filter expression | FilterExpression (a Boolean expression on metadata) | Selects elements from a package or namespace based on metadata criteria |
| Product line package | Package with mixed variation/non-variation content | Organises shared platform elements alongside variation points for a product family |
In KerML, isVariation is a Boolean property on any Usage. When set to true, the usage becomes a variation point. Its owned members with VariantMembership are the allowed choices. SysML v2 provides the variation and variant keywords as syntactic sugar for this mechanism.
Variation Points
KerML origin: variation → Usage with isVariation = true
A variation point is a feature in a model that represents a choice — a place where different configurations may differ. In SysML v2, you declare a variation point by prefixing a usage with the variation keyword. The variation usage itself is not a concrete element; it is a placeholder that must be resolved to one of its variants in any complete configuration.
Think of a restaurant menu. The “Main Course” slot on the menu is a variation point — every diner must choose exactly one option. The individual dishes (steak, fish, pasta) are variants. The menu defines the structure; each diner’s order is a configuration.
Variation on part usages
The most common form of variation applies to part usages within a part definition. The variation keyword declares that the feature is a point of variability, and variant members declare the allowed alternatives:
1 part def Vehicle {
2 part engine : Engine;
3
4 // Variation point: transmission type
5 variation part transmission : Transmission {
6 variant part manual : ManualTransmission;
7 variant part automatic : AutomaticTransmission;
8 variant part cvt : CVTTransmission;
9 }
10 }
In this model, every instance of Vehicle must have exactly one transmission — either manual, automatic, or CVT. The variation point is not optional; it mandates a choice.
Variation on attribute usages
Variation points are not limited to parts. You can apply them to attributes, ports, or any other usage kind:
1 part def Display {
2 // Variation point: screen resolution
3 variation attribute resolution : ScreenResolution {
4 variant attribute hd : HD; // 1280x720
5 variant attribute fhd : FHD; // 1920x1080
6 variant attribute uhd : UHD; // 3840x2160
7 }
8 }
A variation point must contain at least one variant member. Declaring a variation usage with no variants is a semantic error — there is no choice to make. Tooling should flag this as incomplete.
Variant Definitions
KerML origin: variant → VariantMembership (a kind of OwningMembership)
A variant is a concrete alternative within a variation point. Each variant is a fully specified element — it carries its own features, constraints, and sub-structure. When a configuration selects a variant, that variant’s full definition replaces the variation point in the resolved model.
Inline variant definitions
Variants can be defined inline within the variation point, carrying their own unique features:
1 part def Powertrain {
2 variation part motorType : Motor {
3 variant part ice : ICEMotor {
4 attribute displacement : ISQ::VolumeValue;
5 attribute cylinders : ScalarValues::Integer;
6 }
7 variant part electric : ElectricMotor {
8 attribute peakPower : ISQ::PowerValue;
9 attribute batteryCapacity : ISQ::EnergyValue;
10 }
11 variant part hybrid : HybridMotor {
12 attribute displacement : ISQ::VolumeValue;
13 attribute peakPower : ISQ::PowerValue;
14 }
15 }
16 }
Referencing external variant definitions
Variants can also reference separately defined part definitions. This is useful when the same variant appears in multiple variation points across the model:
1 part def ManualTransmission :> Transmission {
2 attribute gearCount : ScalarValues::Integer;
3 }
4
5 part def AutomaticTransmission :> Transmission {
6 attribute modes : DriveMode[1..*];
7 }
8
9 part def Vehicle {
10 // Variants reference externally defined part defs
11 variation part transmission : Transmission {
12 variant part manual : ManualTransmission;
13 variant part automatic : AutomaticTransmission;
14 }
15 }
Variation definitions
You can also mark an entire definition as a variation using variation part def. This means the definition itself is abstract — it cannot be instantiated directly but must be resolved to one of its variant members:
1 variation part def DriveMode {
2 variant eco : EcoMode;
3 variant sport : SportMode;
4 variant normal: NormalMode;
5 }
The distinction between variation on a usage and variation on a definition is important. A variation usage is a specific feature that must be resolved in context. A variation definition declares that the type itself is a variation — every usage of that definition inherits the variation point semantics.
Configuration Management
KerML origin: Configuration binding → BindingConnector resolving a variation to a specific variant
A configuration is a concrete resolution of all variation points in a model. It selects exactly one variant for each variation point, producing a fully specified product instance. In SysML v2, configurations are modelled by specialising the product definition and binding each variation usage to its chosen variant.
Creating a configuration by specialisation
The standard pattern is to create a new part definition or usage that specialises the variable product and binds each variation point:
1 // Base product with variation points
2 part def Vehicle {
3 part engine : Engine;
4 variation part transmission : Transmission {
5 variant part manual : ManualTransmission;
6 variant part automatic : AutomaticTransmission;
7 }
8 variation part infotainment : Infotainment {
9 variant part basic : BasicInfotainment;
10 variant part premium : PremiumInfotainment;
11 }
12 }
13
14 // Configuration: Sport Edition
15 part def SportEdition :> Vehicle {
16 // Resolve transmission to manual
17 part transmission redefines Vehicle::transmission = manual;
18 // Resolve infotainment to premium
19 part infotainment redefines Vehicle::infotainment = premium;
20 }
21
22 // Configuration: Economy Edition
23 part def EconomyEdition :> Vehicle {
24 part transmission redefines Vehicle::transmission = automatic;
25 part infotainment redefines Vehicle::infotainment = basic;
26 }
Partial configurations
Not every configuration must resolve all variation points. A partial configuration resolves some variation points while leaving others open. This is useful for modelling product tiers or regional variants where some choices are fixed but others remain flexible:
1 // Partial configuration: European variant (fixes transmission, leaves infotainment open)
2 part def EuropeanVehicle :> Vehicle {
3 part transmission redefines Vehicle::transmission = manual;
4 // infotainment variation point remains unresolved
5 }
6
7 // Full configuration: European Sport (resolves remaining variation)
8 part def EuropeanSport :> EuropeanVehicle {
9 part infotainment redefines Vehicle::infotainment = premium;
10 }
Use partial configurations to build a layered configuration hierarchy. Start with a base product, create regional or tier-level partial configurations, and then create fully resolved configurations at the leaf level. This mirrors how automotive OEMs manage product lines in practice.
Filtering & Selection
KerML origin: filter → FilterExpression (Boolean expression on metadata)
Filter expressions provide a query mechanism for selecting elements from a namespace based on metadata criteria. Unlike direct variant binding, filters work across packages and can select multiple elements simultaneously. They are especially powerful when combined with metadata annotations.
Basic filter syntax
A filter expression is a Boolean predicate applied to elements in a package. Only elements satisfying the predicate are included in the filtered view:
1 // Metadata for tagging elements
2 metadata def Region {
3 attribute name : ScalarValues::String;
4 }
5
6 metadata def Tier {
7 attribute level : ScalarValues::String;
8 }
9
10 package AllFeatures {
11 part heatedSeats : HeatedSeats {
12 @Region { name = "EU"; }
13 @Tier { level = "premium"; }
14 }
15 part airCon : AirConditioning {
16 @Region { name = "ALL"; }
17 @Tier { level = "basic"; }
18 }
19 part sunroof : PanoramicSunroof {
20 @Region { name = "US"; }
21 @Tier { level = "premium"; }
22 }
23 }
Applying filter expressions
Filter expressions select elements from a package based on their metadata. The filtered package acts as a view — it does not duplicate elements but provides a scoped subset:
1 // Select only premium-tier features
2 package PremiumFeatures filter Region::name == "ALL" or Tier::level == "premium";
3
4 // Select only EU-region features
5 package EUFeatures filter Region::name == "EU" or Region::name == "ALL";
Filter expressions operate on metadata annotations. They do not modify the underlying model — they produce a view of the model that includes only matching elements. This is conceptually similar to a database query: the data is unchanged, but the result set is narrowed.
Combining filters with variations
Filters and variation points are complementary mechanisms. Variation points define mandatory choices (you must pick one). Filters define optional inclusion (include if criteria are met). A well-designed product line uses both:
- Variation points for structural alternatives (engine type, body style)
- Filters for feature packages (comfort options, regional compliance features)
Do not use filters as a substitute for variation points. A filter selects from an existing set; a variation point declares a mandatory choice. If every product must have exactly one of several alternatives, use variation/variant. If a feature is conditionally included based on metadata, use filter.
Product Line Modelling
KerML origin: Product line → Package with mixed variation/non-variation content
A product line is a family of products that share a common platform but differ in specific features. SysML v2 supports product line modelling through a combination of shared definitions (the platform), variation points (the configurable aspects), and configurations (the resolved products).
Platform + variant strategy
The recommended pattern separates the model into three layers:
- Platform package — shared definitions, invariant structure, common constraints
- Variability package — variation points and variant definitions
- Configuration package — fully resolved products that bind all variation points
1 package Platform {
2 // Shared across all products
3 part def Chassis { attribute wheelbase : ISQ::LengthValue; }
4 part def BrakeSystem { part frontBrakes : DiscBrake; part rearBrakes : DiscBrake; }
5 part def SteeringSystem { attribute ratio : ScalarValues::Real; }
6 }
7
8 package Variability {
9 private import Platform::*;
10
11 part def ProductVehicle {
12 part chassis : Chassis; // from platform (invariant)
13 part brakes : BrakeSystem; // from platform (invariant)
14 part steering : SteeringSystem; // from platform (invariant)
15
16 // Variable aspects
17 variation part body : BodyStyle {
18 variant part sedan : SedanBody;
19 variant part suv : SUVBody;
20 variant part truck : TruckBody;
21 }
22 variation part powertrain : Powertrain {
23 variant part petrol : PetrolPowertrain;
24 variant part diesel : DieselPowertrain;
25 variant part electric : ElectricPowertrain;
26 }
27 }
28 }
29
30 package Configurations {
31 private import Variability::*;
32
33 part def SedanPetrol :> ProductVehicle {
34 part body redefines ProductVehicle::body = sedan;
35 part powertrain redefines ProductVehicle::powertrain = petrol;
36 }
37
38 part def SUVElectric :> ProductVehicle {
39 part body redefines ProductVehicle::body = suv;
40 part powertrain redefines ProductVehicle::powertrain = electric;
41 }
42 }
Constraint propagation across variants
Constraints defined on the platform or base product apply to all configurations. Variant-specific constraints can be added at the variant level:
1 part def ProductVehicle {
2 // Platform constraint: applies to ALL configurations
3 assert constraint maxWeight {
4 chassis.totalMass <= 2500[kg]
5 }
6
7 variation part body : BodyStyle {
8 variant part truck : TruckBody {
9 // Variant-specific constraint: only applies when truck is selected
10 assert constraint towingCapacity {
11 payloadCapacity >= 1000[kg]
12 }
13 }
14 }
15 }
The three-layer pattern (platform, variability, configuration) scales well. The platform package can be maintained by a platform engineering team, the variability package by product management, and the configuration package by specific product teams. Each layer imports from the one below.
Complete Worked Example
The following model integrates all concepts from this module: a vehicle product line with sedan, SUV, and truck variants sharing a common platform, each with powertrain and feature-level variability, metadata-driven filtering, and fully resolved configurations.
1 package VehicleProductLine {
2 private import ISQ::*;
3 private import SI::*;
4 private import ScalarValues::*;
5
6 // ── Metadata for filtering ──────────────────────────────
7 metadata def MarketRegion {
8 attribute region : String;
9 }
10 metadata def FeatureTier {
11 attribute tier : String;
12 }
13
14 // ── Shared platform ─────────────────────────────────────
15 part def Chassis {
16 attribute wheelbase : LengthValue;
17 attribute curbWeight : MassValue;
18 }
19 part def BrakeSystem {
20 part frontBrakes : DiscBrake;
21 part rearBrakes : DiscBrake;
22 part abs : ABSController;
23 }
24 part def SteeringSystem {
25 attribute steeringRatio : Real;
26 }
27
28 // ── Body style variants ──────────────────────────────────
29 part def BodyStyle;
30 part def SedanBody :> BodyStyle {
31 attribute doorCount : Integer = 4;
32 attribute trunkVolume : VolumeValue;
33 }
34 part def SUVBody :> BodyStyle {
35 attribute doorCount : Integer = 5;
36 attribute groundClearance : LengthValue;
37 attribute roofRails : Boolean = true;
38 }
39 part def TruckBody :> BodyStyle {
40 attribute doorCount : Integer = 4;
41 attribute bedLength : LengthValue;
42 attribute payloadCapacity : MassValue;
43 }
44
45 // ── Powertrain variants ──────────────────────────────────
46 part def Powertrain;
47 part def PetrolPowertrain :> Powertrain {
48 attribute displacement : VolumeValue;
49 attribute cylinders : Integer;
50 attribute maxPower : PowerValue;
51 }
52 part def DieselPowertrain :> Powertrain {
53 attribute displacement : VolumeValue;
54 attribute maxTorque : ForceValue;
55 }
56 part def ElectricPowertrain :> Powertrain {
57 attribute batteryCapacity : EnergyValue;
58 attribute range : LengthValue;
59 attribute chargePower : PowerValue;
60 }
61
62 // ── Optional feature packages (metadata-tagged) ─────────
63 package FeatureCatalog {
64 part heatedSeats : HeatedSeats {
65 @MarketRegion { region = "ALL"; }
66 @FeatureTier { tier = "premium"; }
67 }
68 part adaptiveCruise : AdaptiveCruiseControl {
69 @MarketRegion { region = "ALL"; }
70 @FeatureTier { tier = "premium"; }
71 }
72 part towHitch : TowHitch {
73 @MarketRegion { region = "US"; }
74 @FeatureTier { tier = "basic"; }
75 }
76 part headlightWashers : HeadlightWashers {
77 @MarketRegion { region = "EU"; }
78 @FeatureTier { tier = "basic"; }
79 }
80 }
81
82 // ── Base product with variation points ───────────────────
83 part def Vehicle {
84 // Platform (invariant across all configurations)
85 part chassis : Chassis;
86 part brakes : BrakeSystem;
87 part steering : SteeringSystem;
88
89 // Variation point 1: body style
90 variation part body : BodyStyle {
91 variant part sedan : SedanBody;
92 variant part suv : SUVBody;
93 variant part truck : TruckBody;
94 }
95
96 // Variation point 2: powertrain
97 variation part powertrain : Powertrain {
98 variant part petrol : PetrolPowertrain;
99 variant part diesel : DieselPowertrain;
100 variant part electric : ElectricPowertrain;
101 }
102
103 // Platform constraint: all variants must satisfy
104 assert constraint maxGrossWeight {
105 chassis.curbWeight <= 3000[kg]
106 }
107 }
108
109 // ── Filtered feature views ───────────────────────────────
110 package PremiumFeatures filter FeatureTier::tier == "premium";
111 package USFeatures filter MarketRegion::region == "US"
112 or MarketRegion::region == "ALL";
113 package EUFeatures filter MarketRegion::region == "EU"
114 or MarketRegion::region == "ALL";
115
116 // ── Fully resolved configurations ────────────────────────
117 part def SedanPetrolUS :> Vehicle {
118 part body redefines Vehicle::body = sedan;
119 part powertrain redefines Vehicle::powertrain = petrol;
120 // Include US-market features from the filtered view
121 }
122
123 part def SUVElectricEU :> Vehicle {
124 part body redefines Vehicle::body = suv;
125 part powertrain redefines Vehicle::powertrain = electric;
126 // Include EU-market features from the filtered view
127 }
128
129 part def TruckDieselUS :> Vehicle {
130 part body redefines Vehicle::body = truck;
131 part powertrain redefines Vehicle::powertrain = diesel;
132
133 // Truck-specific constraint override
134 assert constraint towRating {
135 body.payloadCapacity >= 1500[kg]
136 }
137 }
138 }
This model demonstrates: a shared platform (chassis, brakes, steering), two variation points (body style, powertrain) with three variants each, metadata-tagged optional features with filter expressions for market regions and tiers, platform-level constraints that apply to all configurations, variant-specific constraints (truck tow rating), and three fully resolved configurations targeting different market segments.
Module Summary
| SysML v2 concept | KerML origin | Key rule |
|---|---|---|
variation (on usage) | Usage with isVariation = true | Marks a feature as a variation point; must be resolved to exactly one variant |
variant | VariantMembership | Declares one allowed alternative within a variation point |
variation part def | PartDefinition with isVariation = true | The definition itself is a variation; every usage inherits variation semantics |
| Configuration binding | BindingConnector | Resolves a variation usage to a specific variant via redefines |
| Partial configuration | Specialisation with some variations unresolved | Fixes some choices, leaves others open for further specialisation |
filter expression | FilterExpression | Selects elements from a namespace based on metadata criteria; produces a view |
| Product line package | Package with mixed content | Three-layer pattern: platform + variability + configurations |
| Metadata tagging | Metadata annotations | Annotates elements with region, tier, or other selection criteria for filtering |