Chapter 11. Modeling the State Structure of a System
In SysML2, the state structure of a system is captured by modeling all types of items and parts the system consists of. This also includes modeling their attributes, subparts and any connections between them, as well as their ports and any interfaces between them.
SysML's state structure modeling concepts include Attributes, Enumerations, Occurrences, Items, Parts, Connections, Ports and Interfaces, as shown in the following diagram.
11.1. Attributes and Enumerations
In SysML v2, attributes (officially called "attribute usages") are data-valued features, corresponding to data-valued properties in OWL, as opposed to occurrence-valued features, such as item properties (or "usages") and part properties (or "usages"), corresponding to object-valued properties in OWL.
In the simplest case, an attribute is declared with a KerML data type as its range (such as the primitive data types String, Boolean, Integer, Natural, Rational, or Real), as in the following example:
item def Person { attribute name : String; attribute age : Natural; }
What is called an "attribute definition" in SysML2 is, in fact, a data type definition (defining a set of data values). In the following example, the data type NegativeInteger is defined by constraining the values of the primitive KerML data type Integer:
attribute def NegativeInteger specializes Integer { assert constraint { that < 0 } }
Notice that the keyword that has to be used here for referring to the instances of the containing data type definition of NegativeInteger in the constraint body (see also Section 10.1).
Quantity Types and Quantity Attributes
The ISQ package of the Quantities and Units Domain Library of SysML v2 provides a number of predefined generic quantity attributes (or "attribute usages"), like for instance,
attribute length : LengthValue; attribute mass : MassValue; attribute time : TimeValue;
Notice that the domain (or featuring type) of these predefined attributes is the classifier Anything, so they are inherited by any classifier whenever the ISQ package is imported in a system model. For more on quantities and units, see 14. Quantity Values and Quantity Types.
Enumerations
An enumeration definition is a kind of data type that defines a (typically small) set of names as its enumerated values, like the names "male" and "female" for the two biological sexes in the following example:
enum def Sex { enum male; enum female; }
The declaration of an enumerated value may omit the enum keyword:
enum def Sex { male; female; }
An enumeration definition can be used for declaring an attribute the values of which are limited to the defined set of enumerated values. For instance, in the following example, an instance of the item type Person must have either "male" or "female" as the value of its sex attribute:
item def Person { attribute name : String; attribute sex : Sex; } item def Female specializes Person { attribute redefines sex = Sex::female; }
Notice how the attribute sex is bound to the specific value "female" by means of redefinition, effectively expressing the constraint that a female person is a person having the sex attribute value "female".
An enumeration definition may subclassify other data types. However, an enumeration definition must not subclassify another enumeration definition.
In the SysML spec, enumerations are considered as special kinds of variations and its enumerated values as its variants. However, there is no need for, and no gain of, such a treatment. It's preferable to simply stick to the classical view of an enumeration.
11.2. Items and Parts
SysML2 distinguishes between two kinds of objects:
- An object that is neither a system nor a part of a system is an item.
- A part is an item that is a system or a part of a system.
While parts are items that may perform actions, items that are not parts do not perform actions.
The term item is used as a synonym of the KerML term object. Consequently, an item definition, as a kind of occurrence type definition, actually defines an object type, while an item "usage" is an item-valued property.
In the following example, there is an item definition Person and an item property driver:
item def Person; part def Vehicle { attribute mass : Real; ref item driver : Person; }
A system is modeled as a composite part, and its parts may themselves have further composite structure. Parts may have ports that define the connection points at which those parts may be interconnected for allowing flows of signals/messages or of physical substances. Parts may also perform actions and exhibit states.
A part can represent any level of abstraction, such as a purely logical component, a physical component (with a part number), or some intermediate abstraction. Parts can also be used to represent different kinds of system components such as hardware components, software components, facilities, organizations, or users of a system.
In the following example, there are four part definitions (Engine, Wheel, Person and Vehicle), and there are three part properties (eng, wheels, and driver):
part def Engine; part def Wheel; part def Person; part def Vehicle { attribute mass : Real; part eng : Engine; part wheels[4]: Wheel; ref part driver[0..1] : Person; }
Notice that part properties, such as Vehicle::eng and Vehicle::wheels in the example above, are composite features by default, while the part property Vehicle::driver is declared as a referential (non-composite) feature, which implies that the driver of a vehicle is not necessarily destroyed when the vehicle is destroyed.
11.3. Property Value Relationships
A property value relationship (called "feature value" in the spec) is a special kind of binding connector that binds a (possibly initial or default) value to a property.
An example of a bound property value relationship, stating that a property's value is always obtained as the result of the value expression, and in this sense derived:
derived attribute averageScore : Rational = sum(scores)/size(scores);
Notice that designating a bound property value relationship as derived is not required.
An example of an initial property value relationship, stating that a property's initial value is obtained as the result of the value expression (but may be changed subsequently):
attribute count : Natural := 0;
An example of a bound property default value relationship:
attribute cutoff : Integer default = 0.75 * averageScore;
An example of an initial property default value relationship:
part engine : Engine default := standardEngine;
These different forms of property value relationships combine the definition of a property (structural feature) with different forms of bindings.
11.4. Connections and Bindings
A connection between two (or more) items or parts may be an abstract relationship (a link) or a concrete relationship in the form of a link object, which is an instance of an association structure, possibly having its own characteristics.
A connection type definition defines both an association (e.g., between part types) and a kind of part type that classifies connections between related things, such as items and parts. The features of a connection type that are not connection ends allow to characterize connections, as shown in the following example:
part def Hub {...} part def Device {...} connection def DeviceConnection { end [0..1] part hub : Hub; end [1..*] part device : Device; attribute bandwidth : Real; }
A connection type often represents logical connections that abstract away details of how the involved parts are connected. For example, plumbing that includes pipes and fittings may be used to connect a pump and a tank. It is sometimes desired to model the connection of the pump to the tank at a more abstract level without including the plumbing. This is viewed as a logical connection between the pump and the tank.
Alternatively, the plumbing can be modeled as a part where the pump connects to the plumbing, and the plumbing connects to the tank. As a part itself, a connection can contain the plumbing either as a composite feature, or as a reference to the plumbing that is owned by a higher level pump-tank system context. In this way, the logical connection without structure can be refined into a physical connection.
In the following example, a binary Mounting connection type (or association) allows connecting an axle to two wheels by requiring that its population includes exactly two links for each instance of Axle linking it to two different instances of Wheel.
While all end properties of a connection type, here mountingAxle and mountedWheel, have the multiplicity 1, the multiplicities across their respective association lines, marked in yellow, are called their cross multiplicities and are expressed in-between the keyword end and the end property name in the textual notation:
part def Axle {...} part def Wheel {...} connection def Mounting { end [1] part mountingAxle : Axle; end [2] part mountedWheel : Wheel; }
Notice that the cross multiplicity [2] of the end property mountedWheel expresses the constraint that for any instance of Axle, there are exactly two Mounting links in the extent of the connection type linking the axle to two different wheels. Likewise, the cross multiplicity [1] of the end property mountingAxle expresses the constraint that for any instance of Wheel, there is exactly one Mounting link connecting the wheel to an axle.
A connection property ("usage") is a part property that is also a KerML connector, so it is typed by an association, having values that are links.
A connection usage redefines the connection ends from its definition, associating those ends with the specific usage elements that are to be connected. For example, a connection definition could have connection ends that are part usages defined by part definitions Pump and Tank. A usage of this connection definition would then associate corresponding connection ends with specific pump and tank part usages. Supposing that the pump and tank part usages have multiplicity 1, then this means that the single value of the pump usage is to be connected to the single value of the tank usage.
A connection usage that connects parts is often a logical connection that abstracts away details of how the parts are connected. For example, plumbing that includes pipes and fittings may be used to connect a pump and a tank. It is sometimes desired to model the connection of the pump to the tank at a more abstract level without including the plumbing.
In the following example, the connection property mount, which is typed by the Mounting connection type defined above, requires having exactly two values, each one representing a connection between the AxleAssembly's axle and one of its wheels:
part def AxleAssembly { part axle[1] : Axle; part wheels[2] : Wheel; connection mount[2] : Mounting { end part mountingAxle references axle; end part mountedWheel references wheels; } }
This syntax also allows the declaration of ternary (or n-ary) connection properties:
connection def TwoWheelsMounting { end [1] part mountingAxle : Axle; end [1] part leftWheel : Wheel; end [1] part rightWheel : Wheel; } part def AxleAssembly { part axle[1] : Axle; part leftWheel[1] : Wheel; part rightWheel[1] : Wheel; connection mount[1] : TwoWheelsMounting { end part mountingAxle references axle; end part mountedLeftWheel references leftWheel; end part mountedRightWheel references rightWheel; } }
There are three shorthand notations for connection properties.
The related features of the connection property may be identified in a comma-separated list, between parentheses (...), preceded by the keyword connect:
connection mount[1] : TwoWheelsMounting connect ( mountingAxle ::> axle, mountedLeftWheel ::> leftWheel, mountedRightWheel ::> rightWheel )
Notice that, for brevity, the symbol ::> is used here instead of the keyword references. A declaration without a name and a type allows the simplest syntax for declaring a ternary (or an n-ary) connection property:
connect ( axle, leftWheel, rightWheel )
However, this form of declaration implies that the type of connections is given by the predefined (most general) connection type Connection.
If the connection property is typed by a binary association, a further shorthand notation may be used:
connection mount[2] : Mounting connect mountingAxle ::> axle to mountedWheel ::> wheels;
Or, further simplified by leaving the redefinition of the connected features implicit:
connection mount[2] : Mounting connect axle to wheels;
A binary connection property can also be declared without a name and a type:
part def DeviceConfiguration { part hub : Hub; part device : Device; connect hub to device; }
In this case, the predefined generic connection type BinaryConnection is used as its implicit type.
Binding Connections
A binding connection asserts a value equality between two different features. In KerML, bindings are binary connectors that require their source and target features to have the same values on each instance of their domain.
part def Vehicle { part fuelTank { out fuelFlowOut : Fuel; } part engine { in fuelFlowIn : Fuel; } binding fuelFlowBinding bind fuelTank.fuelFlowOut = engine.fuelFlowIn; }
In the SysML v2 spec, for terminological reasons, bindings (and successions) are redefined as special kinds of connection "usages". However, semantically, there is no need for such a redefinition. It's preferable to simply keep the KerML concept of a binding as a special kind of connector.
11.5. Ports and Interfaces
A port represents a connection point that can be connected to another port via an interface.
Ports as Connection Points
Ports are connected with each other for enabling transfers (e.g., of signals or physical quantities) between systems or their parts. The properties of a port specify what can be exchanged in such transfers.
Connected ports must conform: each feature of a port at one end of a connection must have a matching feature on a port at the other end of the connection. Two features match if they have conforming definitions and either both have no direction or they have conjugate directions. The conjugate of direction in is out and vice versa, while direction inout is its own conjugate. A transfer can occur from the out features of one port usage to the matching in features of connected port usages. Transfers can occur in both directions between matching inout features. [7.12.1]
A port type is a KerML "Structure" (object type) and, consequently, a port property ("usage"), as a non-composite feature, references port objects.
The following example illustrates how the conjugated ports FuelOutPort and FuelInPort match by having the same features with the direction of directed features being reversed:
port def FuelOutPort { attribute temperature : Real; out item fuelSupply : Fuel; } port def FuelInPort { attribute temperature : Real; in item fuelSupply : Fuel; } part def FuelTankAssembly { port fuelTankPort : FuelOutPort; } part def Engine { port engineFuelPort : FuelInPort; }
Every port definition also implicitly declares a conjugated port definition, which has the same features, except that any directed features have conjugated directions (i.e., in and out are reversed, with inout unchanged). The name of the conjugated port definition is always given by the name of the original port definition with the character ~ prepended, in the namespace of the original port definition. [7.12.3]
Thus, the example above can be rewritten in the following way:
port def FuelOutPort { attribute temperature : Real; out item fuelSupply : Fuel; } part def FuelTankAssembly { port fuelTankPort : FuelOutPort; } part def Engine { port engineFuelPort : ~FuelOutPort; }
Interfaces
An interface type is a connection type for connecting ports (that is, all of its ends are port properties). An interface property ("usage") is a connection property for connecting ports.
In the following example, an anonymous interface property of a DistributedSystem (without a specific type) connects a client port to a server port for allowing request-response signaling:
part def DistributedSystem { item def Request; item def Response; part client { port clientPort; action clientBehavior { send new Request() via clientPort; then accept Response via clientPort; } } part server { port serverPort; action serverBehavior { accept Request via serverPort; then send new Response() via serverPort; } } interface client.clientPort to server.serverPort; }
Another example (based on an example presented by Michael Jastram) describes an apartment as a complex system such that a device like a toaster is connected to a power outlet via an interface:
private import SI::V; private import SI::A; port def PowerOutletPort { out power :> ISQ::electricPower; attribute voltage :> ISQ::voltage = 230 [V]; attribute maxCurrent : ISQ::ElectricCurrentValue = 16 [A]; } port def DevicePowerPort { in power :> ISQ::electricPower; attribute voltage :> ISQ::voltage = 230 [V]; attribute maxCurrent : ISQ::ElectricCurrentValue; } interface def Device2PowerOutletInterface { end port outletPort : PowerOutletPort; end port devicePort : DevicePowerPort; } part def Apartment { part kitchen { port outletPort : PowerOutletPort; } part toaster { port powerPort : DevicePowerPort { :>> maxCurrent = 2 [A]; } } interface : Device2PowerOutletInterface connect devicePort ::> toaster.powerPort to outletPort ::> kitchen.outletPort; }